Adrian Marino

Claudio Collado

Inicialización

Fijamos la semilla para poder reproducir los experimentos. También se fija el numero de CPU’s a utilizar.

set.seed(42)
options(mc.cores = 24)

Librerias

Se importan las librerías a utilizar a lo largo de la notebook:

# install.packages(pacman)
# install.packages("https://cran.r-project.org/src/contrib/rstan_2.21.2.tar.gz",repos = NULL,type="source")
# sudo apt-get install libglpk-dev
library(pacman)
p_load(tidyverse, tidymodels, rsample, rstan, shinystan, rstanarm, devtools)

source('../src/dataset.R')
source('../src/plot.R')
source('../src/model.R')

Dataset y Analisis Exploratorio

Palmer Penguins

Palmer Penguins

1. Lectura del dataset

dataset <- load_dataset() %>% mutate_if(is.character, as.factor)
Rows: 344 Columns: 8
── Column specification ───────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr (3): species, island, sex
dbl (5): bill_length_mm, bill_depth_mm, flipper_length_mm, body_mass_g, year

ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
dataset %>% glimpse()
Rows: 344
Columns: 8
$ species           <fct> Adelie, Adelie, Adelie, Adelie, Adelie, Adelie, Adelie, Adelie, Adelie, Adelie,…
$ island            <fct> Torgersen, Torgersen, Torgersen, Torgersen, Torgersen, Torgersen, Torgersen, To…
$ bill_length_mm    <dbl> 39.1, 39.5, 40.3, NA, 36.7, 39.3, 38.9, 39.2, 34.1, 42.0, 37.8, 37.8, 41.1, 38.…
$ bill_depth_mm     <dbl> 18.7, 17.4, 18.0, NA, 19.3, 20.6, 17.8, 19.6, 18.1, 20.2, 17.1, 17.3, 17.6, 21.…
$ flipper_length_mm <dbl> 181, 186, 195, NA, 193, 190, 181, 195, 193, 190, 186, 180, 182, 191, 198, 185, …
$ body_mass_g       <dbl> 3750, 3800, 3250, NA, 3450, 3650, 3625, 4675, 3475, 4250, 3300, 3700, 3200, 380…
$ sex               <fct> male, female, female, NA, female, male, female, male, NA, NA, NA, NA, female, m…
$ year              <dbl> 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2…

2. Variables

Se enumeran y describen breve-mente cada variable que forma parte del dataset:

Variables Numéricas:

  • bill_length_mm: Longitud del pico del individuo medida en milímetros (también conocida como longitud del culmen).
  • bill_depth_mm: Profundidad del pico del individuo medida en milímetros (también conocida como profundidad del culmen).
  • flipper_length_mm: Longitud de la aleta del individuo medida en milímetros.
  • body_mass_g: Masa corporal del individuo medida en gramos.
  • year: Año en el que se registra el individuo.

Variables Categóricas:

  • species: Especie del individuo (Adelie, Gentoo ;) o Chinstrap).
  • sex: Sexo del individuo.
  • island: Isla donde se encontré el individuo (Biscoe, Dream o Torgersen).

3. Resumen de faltantes

missings_summary(dataset)

4. Varibles numericas

hist_plots(dataset)

Observaciones

  • Se aprecia que cada año se registro prácticamente el mismo numero de individuos.
  • La distribución de la masa corporal de los individuos tiene una asimétrica positiva. Tenemos muchos individuos con valores bajos de masa corporal, con una media de 192 gramos. Luego tenemos menos individuos con valores mas alto.
  • La longitud de la aleta parece ser una distribución bi-modal. Tenemos dos modas una 192 mm y otra en 215 mm.
  • La longitud del pico también parece tener una ligera simetría positiva. Es decir que lo individuos con menor peso tiene pico mas pequeños.
  • Por otro lado la profundidad de pico parece tener una ligera simetría positiva.
box_plots(dataset)

Observaciones

  • COMPLETAR

Outliers

No se registran valores mas extremos que el mínimo y máximo valor en cada variables. Es decir que no encontramos outliers.

outliers(dataset, column='bill_length_mm')
$inf
[1] 32.1

$sup
[1] 59.6

outliers(dataset, column='bill_length_mm')
$inf
[1] 32.1

$sup
[1] 59.6

outliers(dataset, column='bill_depth_mm')
$inf
[1] 13.1

$sup
[1] 21.5

outliers(dataset, column='flipper_length_mm')
$inf
[1] 172

$sup
[1] 231

outliers(dataset, column='body_mass_g')
$inf
[1] 2700

$sup
[1] 6300

outliers(dataset, column='year')
$inf
[1] 2007

$sup
[1] 2009

bar_plots(dataset)

Observaciones

  • La variable sexo se encuentra balanceada. Por otro lado, contiene algunos valores faltantes.
  • La variable island esta completamente desbalanceada. Esto seguramente se debe a una diferencia en numero en las poblaciones en cada isla o a un sesgo al momento de registrar los individuos. Es decir que registramos con individuos en una isla que en otra.
  • Lo mismo sucede con las especies de individuos. Vemos un gran desbalance entre la especie Chinstrap vs. otra especies. Por otro aldo Adelie y Gentoo tiene un conteo mas cercano

5. Excluir observaciones con missings

dataset <- dataset %>% drop_na()
missings_summary(dataset)
Warning: attributes are not identical across measure variables;
they will be dropped

6. Correlaciones

corr_plot(dataset %>% dplyr::select(-year))

segmented_pairs_plot(dataset, segment_column='species')
`stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
`stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
`stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
`stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
`stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
`stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
`stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
`stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
`stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
`stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
`stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
`stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
`stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
`stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
`stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

Experimentos

Experimento 1

  • Solo variables numéricas.
  • Regresión múltiple frecuentista.
  • Regresión múltiple bayesiana con priors normales y exponencial.

1. Split train vs. test

train_test <- train_test_split(dataset, train_size = 0.7, shuffle = TRUE)
[1] "Train set size: 233"
[1] "Test set size: 100"
train_set <- train_test[[1]]
test_set  <- train_test[[2]]

2. Modelo lineal

lineal_model_1 <- lm(
  body_mass_g ~ bill_length_mm + bill_depth_mm + flipper_length_mm,
  data = train_set
)

summary(lineal_model_1)

Call:
lm(formula = body_mass_g ~ bill_length_mm + bill_depth_mm + flipper_length_mm, 
    data = train_set)

Residuals:
    Min      1Q  Median      3Q     Max 
-868.52 -260.19  -17.83  239.28 1269.72 

Coefficients:
                   Estimate Std. Error t value Pr(>|t|)    
(Intercept)       -6074.063    654.637  -9.279   <2e-16 ***
bill_length_mm        3.530      6.297   0.561    0.576    
bill_depth_mm        12.534     16.232   0.772    0.441    
flipper_length_mm    49.318      2.874  17.157   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 382.4 on 229 degrees of freedom
Multiple R-squared:  0.7755,    Adjusted R-squared:  0.7725 
F-statistic: 263.6 on 3 and 229 DF,  p-value: < 2.2e-16

Quitamos los coeficientes que no son significativos para explicar a la variable body_mass_g:

lineal_model_1 <- lm(body_mass_g ~ flipper_length_mm, data = train_set)

summary(lineal_model_1)

Call:
lm(formula = body_mass_g ~ flipper_length_mm, data = train_set)

Residuals:
    Min      1Q  Median      3Q     Max 
-857.93 -257.17  -17.05  232.95 1278.39 

Coefficients:
                   Estimate Std. Error t value Pr(>|t|)    
(Intercept)       -5688.500    353.398  -16.10   <2e-16 ***
flipper_length_mm    49.240      1.749   28.16   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 381.7 on 231 degrees of freedom
Multiple R-squared:  0.7743,    Adjusted R-squared:  0.7734 
F-statistic: 792.7 on 1 and 231 DF,  p-value: < 2.2e-16

3. Modelo bayesiano

bayesion_model_1 <- stan(
  model_code =  "
    data {
      int<lower=1>               obs_count;
      vector<lower=1>[obs_count] x;
      vector[obs_count]          y;
    }
    parameters {
      real          beta0;
      real          beta1;
      real<lower=0> sigma;
    }
    model {
      // Distribuciones a priori (Fijado por el investigador)
      beta0 ~ normal(0, 8000);  // Intercept
      beta1 ~ normal(0, 100);   // flipper_length_mm
      sigma ~ exponential(0.1); // Varianza

      // Likelihood
      y ~ normal(beta0 + beta1 * x, sigma);
    }
  ",
  data = list(
      obs_count = nrow(train_set),
      x         = colvalues(train_set, 'flipper_length_mm'),
      y         = colvalues(train_set, 'body_mass_g')
  ),
  chains = 3,
  iter   = 300,
  warmup = 180,
  thin   = 1
)
starting worker pid=22509 on localhost:11799 at 23:30:25.914
starting worker pid=22546 on localhost:11799 at 23:30:26.021
starting worker pid=22583 on localhost:11799 at 23:30:26.130

SAMPLING FOR MODEL 'c017d4fe4edb4b602fa33b4a46efc8cf' NOW (CHAIN 1).
Chain 1: 
Chain 1: Gradient evaluation took 2e-05 seconds
Chain 1: 1000 transitions using 10 leapfrog steps per transition would take 0.2 seconds.
Chain 1: Adjust your expectations accordingly!
Chain 1: 
Chain 1: 
Chain 1: Iteration:   1 / 300 [  0%]  (Warmup)
Chain 1: Iteration:  30 / 300 [ 10%]  (Warmup)
Chain 1: Iteration:  60 / 300 [ 20%]  (Warmup)
Chain 1: Iteration:  90 / 300 [ 30%]  (Warmup)
Chain 1: Iteration: 120 / 300 [ 40%]  (Warmup)
Chain 1: Iteration: 150 / 300 [ 50%]  (Warmup)
Chain 1: Iteration: 180 / 300 [ 60%]  (Warmup)
Chain 1: Iteration: 181 / 300 [ 60%]  (Sampling)
Chain 1: Iteration: 210 / 300 [ 70%]  (Sampling)
Chain 1: Iteration: 240 / 300 [ 80%]  (Sampling)
Chain 1: Iteration: 270 / 300 [ 90%]  (Sampling)
Chain 1: Iteration: 300 / 300 [100%]  (Sampling)
Chain 1: 
Chain 1:  Elapsed Time: 0.127886 seconds (Warm-up)
Chain 1:                0.087164 seconds (Sampling)
Chain 1:                0.21505 seconds (Total)
Chain 1: 

SAMPLING FOR MODEL 'c017d4fe4edb4b602fa33b4a46efc8cf' NOW (CHAIN 2).
Chain 2: 
Chain 2: Gradient evaluation took 1.6e-05 seconds
Chain 2: 1000 transitions using 10 leapfrog steps per transition would take 0.16 seconds.
Chain 2: Adjust your expectations accordingly!
Chain 2: 
Chain 2: 
Chain 2: Iteration:   1 / 300 [  0%]  (Warmup)
Chain 2: Iteration:  30 / 300 [ 10%]  (Warmup)
Chain 2: Iteration:  60 / 300 [ 20%]  (Warmup)
Chain 2: Iteration:  90 / 300 [ 30%]  (Warmup)
Chain 2: Iteration: 120 / 300 [ 40%]  (Warmup)
Chain 2: Iteration: 150 / 300 [ 50%]  (Warmup)
Chain 2: Iteration: 180 / 300 [ 60%]  (Warmup)
Chain 2: Iteration: 181 / 300 [ 60%]  (Sampling)
Chain 2: Iteration: 210 / 300 [ 70%]  (Sampling)
Chain 2: Iteration: 240 / 300 [ 80%]  (Sampling)
Chain 2: Iteration: 270 / 300 [ 90%]  (Sampling)
Chain 2: Iteration: 300 / 300 [100%]  (Sampling)
Chain 2: 
Chain 2:  Elapsed Time: 0.13672 seconds (Warm-up)
Chain 2:                0.075576 seconds (Sampling)
Chain 2:                0.212296 seconds (Total)
Chain 2: 

SAMPLING FOR MODEL 'c017d4fe4edb4b602fa33b4a46efc8cf' NOW (CHAIN 3).
Chain 3: 
Chain 3: Gradient evaluation took 2e-05 seconds
Chain 3: 1000 transitions using 10 leapfrog steps per transition would take 0.2 seconds.
Chain 3: Adjust your expectations accordingly!
Chain 3: 
Chain 3: 
Chain 3: Iteration:   1 / 300 [  0%]  (Warmup)
Chain 3: Iteration:  30 / 300 [ 10%]  (Warmup)
Chain 3: Iteration:  60 / 300 [ 20%]  (Warmup)
Chain 3: Iteration:  90 / 300 [ 30%]  (Warmup)
Chain 3: Iteration: 120 / 300 [ 40%]  (Warmup)
Chain 3: Iteration: 150 / 300 [ 50%]  (Warmup)
Chain 3: Iteration: 180 / 300 [ 60%]  (Warmup)
Chain 3: Iteration: 181 / 300 [ 60%]  (Sampling)
Chain 3: Iteration: 210 / 300 [ 70%]  (Sampling)
Chain 3: Iteration: 240 / 300 [ 80%]  (Sampling)
Chain 3: Iteration: 270 / 300 [ 90%]  (Sampling)
Chain 3: Iteration: 300 / 300 [100%]  (Sampling)
Chain 3: 
Chain 3:  Elapsed Time: 0.157134 seconds (Warm-up)
Chain 3:                0.067661 seconds (Sampling)
Chain 3:                0.224795 seconds (Total)
Chain 3: 
params_1 <- c('beta0', 'beta1', 'sigma')
traceplot(bayesion_model_1, pars = params_1, inc_warmup = TRUE)

4. Coeficientes

lm_vs_br_coeficients(lineal_model_1, bayesion_model_1, params_1)

4. Validación

vars_1 <- c('flipper_length_mm') 

lm_vs_br_models_validation(lineal_model_1, bayesion_model_1, params_1, vars_1, test_set)
bayesion_predictor_1 <- BayesianRegressionPredictor.from(bayesion_model_1, params_1, vars_1)

plot_compare_fit(
  lineal_model_1, 
  bayesion_predictor_1, 
  train_set,
  label_1 = 'Regresion Lineal', 
  label_2 = 'Regresion Bayesiana'
)

Experimento 2

  • Idem a experimento 1, incorporando una variable categórica.
  • Regresión múltiple frecuentista.
  • Regresión bayesiana con priors normales y exponencial.

1. Modelo lineal

lineal_model_2 <- lm(
    body_mass_g 
      ~ bill_length_mm
      + bill_depth_mm
      + flipper_length_mm
      + sex,

  data = train_set
)

summary(lineal_model_2)

Call:
lm(formula = body_mass_g ~ bill_length_mm + bill_depth_mm + flipper_length_mm + 
    sex, data = train_set)

Residuals:
    Min      1Q  Median      3Q     Max 
-755.02 -255.89   -6.03  221.97  989.38 

Coefficients:
                    Estimate Std. Error t value Pr(>|t|)    
(Intercept)       -1922.6152   729.5654  -2.635  0.00898 ** 
bill_length_mm       -0.5331     5.4439  -0.098  0.92208    
bill_depth_mm       -92.9217    18.2692  -5.086 7.62e-07 ***
flipper_length_mm    37.2016     2.8209  13.188  < 2e-16 ***
sexmale             534.1583    59.5409   8.971  < 2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 329.5 on 228 degrees of freedom
Multiple R-squared:  0.834, Adjusted R-squared:  0.8311 
F-statistic: 286.5 on 4 and 228 DF,  p-value: < 2.2e-16

Quitamos los coeficientes que no son significativos para explicar a la variable body_mass_g:

lineal_model_2 <- lm(
    body_mass_g 
      ~ bill_depth_mm
      + flipper_length_mm
      + sex,
  data = train_set
)

summary(lineal_model_2)

Call:
lm(formula = body_mass_g ~ bill_depth_mm + flipper_length_mm + 
    sex, data = train_set)

Residuals:
    Min      1Q  Median      3Q     Max 
-758.30 -258.55   -5.04  223.02  989.59 

Coefficients:
                   Estimate Std. Error t value Pr(>|t|)    
(Intercept)       -1912.697    720.936  -2.653  0.00853 ** 
bill_depth_mm       -93.106     18.133  -5.135 6.04e-07 ***
flipper_length_mm    37.053      2.373  15.617  < 2e-16 ***
sexmale             533.673     59.206   9.014  < 2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 328.7 on 229 degrees of freedom
Multiple R-squared:  0.834, Adjusted R-squared:  0.8319 
F-statistic: 383.6 on 3 and 229 DF,  p-value: < 2.2e-16

2. Modelo bayesiano

Construimos una matriz con todas las variables(X) mas el intercept:

to_model_input <- function(df) {
  model.matrix(
    body_mass_g 
      ~ bill_depth_mm
      + flipper_length_mm
      + sex,
    data = df
  )
}

train_X <- train_set %>% to_model_input()
test_X  <- test_set %>% to_model_input()

head(train_X)
  (Intercept) bill_depth_mm flipper_length_mm sexmale
1           1          18.8               197       1
2           1          14.6               211       0
3           1          19.1               195       1
4           1          15.9               224       1
5           1          18.5               201       1
6           1          18.3               195       1

Definimos y corremos el modelo bayesiano:

bayesion_model_2 <- stan(
  model_code = "
    data {
      int<lower=1>                 obs_count;
      int<lower=1>                 coef_count;
      matrix[obs_count,coef_count] X;
      vector[obs_count]            y;
    }
    parameters {
      vector[coef_count]  beta;
      real<lower=0>       sigma;
    }
    model {
      // Distribuciones a priori
      beta[1] ~ normal(0, 3000); // Intecept = beta0 + sexfemale
      beta[2] ~ normal(0, 200);  // bill_depth_mm
      beta[3] ~ normal(0, 200);  // flipper_length_mm
      beta[4] ~ normal(0, 600);  // sexmale
  
      sigma ~ exponential(0.1);  // Varianza
  
      // Likelihood
      y ~ normal(X * beta, sigma);
    }
  ",
  data = list(
      obs_count  = dim(train_X)[1],
      coef_count = dim(train_X)[2],
      y          = colvalues(train_set, 'body_mass_g'),
      X          = train_X
  ),
  chains = 3,
  iter   = 4000,
  warmup = 500,
  thin   = 1
)
starting worker pid=22865 on localhost:11799 at 23:31:34.101
starting worker pid=22902 on localhost:11799 at 23:31:34.210
starting worker pid=22939 on localhost:11799 at 23:31:34.320

SAMPLING FOR MODEL '2aabf6de2b4d6f89278592cbff82547b' NOW (CHAIN 1).
Chain 1: 
Chain 1: Gradient evaluation took 1.7e-05 seconds
Chain 1: 1000 transitions using 10 leapfrog steps per transition would take 0.17 seconds.
Chain 1: Adjust your expectations accordingly!
Chain 1: 
Chain 1: 
Chain 1: Iteration:    1 / 4000 [  0%]  (Warmup)
Chain 1: Iteration:  400 / 4000 [ 10%]  (Warmup)
Chain 1: Iteration:  501 / 4000 [ 12%]  (Sampling)
Chain 1: Iteration:  900 / 4000 [ 22%]  (Sampling)
Chain 1: Iteration: 1300 / 4000 [ 32%]  (Sampling)

SAMPLING FOR MODEL '2aabf6de2b4d6f89278592cbff82547b' NOW (CHAIN 2).
Chain 2: 
Chain 2: Gradient evaluation took 1.9e-05 seconds
Chain 2: 1000 transitions using 10 leapfrog steps per transition would take 0.19 seconds.
Chain 2: Adjust your expectations accordingly!
Chain 2: 
Chain 2: 
Chain 2: Iteration:    1 / 4000 [  0%]  (Warmup)
Chain 1: Iteration: 1700 / 4000 [ 42%]  (Sampling)

SAMPLING FOR MODEL '2aabf6de2b4d6f89278592cbff82547b' NOW (CHAIN 3).
Chain 3: 
Chain 3: Gradient evaluation took 1.6e-05 seconds
Chain 3: 1000 transitions using 10 leapfrog steps per transition would take 0.16 seconds.
Chain 3: Adjust your expectations accordingly!
Chain 3: 
Chain 3: 
Chain 3: Iteration:    1 / 4000 [  0%]  (Warmup)
Chain 1: Iteration: 2100 / 4000 [ 52%]  (Sampling)
Chain 2: Iteration:  400 / 4000 [ 10%]  (Warmup)
Chain 2: Iteration:  501 / 4000 [ 12%]  (Sampling)
Chain 1: Iteration: 2500 / 4000 [ 62%]  (Sampling)
Chain 3: Iteration:  400 / 4000 [ 10%]  (Warmup)
Chain 3: Iteration:  501 / 4000 [ 12%]  (Sampling)
Chain 1: Iteration: 2900 / 4000 [ 72%]  (Sampling)
Chain 2: Iteration:  900 / 4000 [ 22%]  (Sampling)
Chain 1: Iteration: 3300 / 4000 [ 82%]  (Sampling)
Chain 3: Iteration:  900 / 4000 [ 22%]  (Sampling)
Chain 2: Iteration: 1300 / 4000 [ 32%]  (Sampling)
Chain 1: Iteration: 3700 / 4000 [ 92%]  (Sampling)
Chain 3: Iteration: 1300 / 4000 [ 32%]  (Sampling)
Chain 2: Iteration: 1700 / 4000 [ 42%]  (Sampling)
Chain 1: Iteration: 4000 / 4000 [100%]  (Sampling)
Chain 1: 
Chain 1:  Elapsed Time: 0.502712 seconds (Warm-up)
Chain 1:                2.31541 seconds (Sampling)
Chain 1:                2.81812 seconds (Total)
Chain 1: 
Chain 2: Iteration: 2100 / 4000 [ 52%]  (Sampling)
Chain 3: Iteration: 1700 / 4000 [ 42%]  (Sampling)
Chain 2: Iteration: 2500 / 4000 [ 62%]  (Sampling)
Chain 3: Iteration: 2100 / 4000 [ 52%]  (Sampling)
Chain 2: Iteration: 2900 / 4000 [ 72%]  (Sampling)
Chain 3: Iteration: 2500 / 4000 [ 62%]  (Sampling)
Chain 2: Iteration: 3300 / 4000 [ 82%]  (Sampling)
Chain 3: Iteration: 2900 / 4000 [ 72%]  (Sampling)
Chain 2: Iteration: 3700 / 4000 [ 92%]  (Sampling)
Chain 3: Iteration: 3300 / 4000 [ 82%]  (Sampling)
Chain 2: Iteration: 4000 / 4000 [100%]  (Sampling)
Chain 2: 
Chain 2:  Elapsed Time: 0.622863 seconds (Warm-up)
Chain 2:                2.7078 seconds (Sampling)
Chain 2:                3.33067 seconds (Total)
Chain 2: 
Chain 3: Iteration: 3700 / 4000 [ 92%]  (Sampling)
Chain 3: Iteration: 4000 / 4000 [100%]  (Sampling)
Chain 3: 
Chain 3:  Elapsed Time: 0.507968 seconds (Warm-up)
Chain 3:                2.8828 seconds (Sampling)
Chain 3:                3.39077 seconds (Total)
Chain 3: 
params_2 <- c('beta[1]', 'beta[2]', 'beta[3]', 'beta[4]', 'sigma')
traceplot(bayesion_model_2, inc_warmup = TRUE, pars = params_2)

3. Coeficientes

lineal_model_2$coefficients
      (Intercept)     bill_depth_mm flipper_length_mm           sexmale 
      -1912.69656         -93.10594          37.05300         533.67323 
br_coeficients(bayesion_model_2, params_2)

4. Validación

vars_2 <- c('bill_depth_mm', 'flipper_length_mm', 'sexmale')

lm_vs_br_models_validation(
  lineal_model_2, 
  bayesion_model_2, 
  params_2,
  vars_2,
  test_set,
  as.data.frame(test_X)
)
bayesion_predictor_2 <- BayesianRegressionPredictor.from(bayesion_model_2, params_2, vars_2)

plot_compare_fit(
  lineal_model_2, 
  bayesion_predictor_2, 
  test_set, 
  as.data.frame(test_X),
  label_1 = 'Regresion Lineal', 
  label_2 = 'Regresion Bayesiana'
)

Experimento 3

  • Idem a experimento 1 incorporando outliers en alguna variable numérica.
  • Regresión múltiple frecuentista.
  • Regresión bayesiana con priors normales y exponencial.

1. Outliers

A continuación vamos a agregar outliers a la variable flipper_length_mm, la cual define la longitud de la aleta del individuo medida en milímetros.

Para visualizar los nuevos outliers a continuación graficamos flipper_length_mm vs. body_mass_g antes y después de agregar outliers:

plot_data(train_set)

train_set_with_outliers <- train_set %>%
  mutate(flipper_length_mm = ifelse(
    body_mass_g > 5400 & body_mass_g < 5700, 
    flipper_length_mm + (flipper_length_mm * runif(1, 0.1, 0.2)), 
    flipper_length_mm
  ))

plot_data(train_set_with_outliers)

2. Modelo lineal

lineal_model_3 <- lm(
  body_mass_g ~ flipper_length_mm,
  data = train_set_with_outliers
)
summary(lineal_model_3)

Call:
lm(formula = body_mass_g ~ flipper_length_mm, data = train_set_with_outliers)

Residuals:
   Min     1Q Median     3Q    Max 
-797.5 -301.7   -9.2  281.6 1165.8 

Coefficients:
                   Estimate Std. Error t value Pr(>|t|)    
(Intercept)       -3722.454    305.332  -12.19   <2e-16 ***
flipper_length_mm    39.167      1.497   26.16   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 403.6 on 231 degrees of freedom
Multiple R-squared:  0.7477,    Adjusted R-squared:  0.7466 
F-statistic: 684.6 on 1 and 231 DF,  p-value: < 2.2e-16

Comparemos el ajuste del modelo lineal ajustando en un dataset de train con y sin outliers:

plot_compare_fit(
  lineal_model_1, 
  lineal_model_3, 
  train_set_with_outliers,
  label_1='Regresión Lineal SIN outliers', 
  label_2='Regresión Lineal CON outliters'
)

Se aprecia que el modelo entrenado en train_set_outliers esta apalancado por las observaciones atípicas

2. Modelo lineal Robusto

Entrenamos una regresión lineal múltiple robusta para intentar de disminuir el efecto de los nuevos outliers:

robust_lineal_model_3 <- rlm(
  body_mass_g ~ flipper_length_mm,
  data = train_set_with_outliers
)
plot_compare_fit(
  lineal_model_1, 
  robust_lineal_model_3, 
  train_set_with_outliers,
  label_1='Regresión Lineal SIN outliers', 
  label_2='Regresión Lineal Robusta CON outliters'
)

Gráficamente no se llega a distinguir pero el modelo robusto termina ajustando mejor que el modelo lineal clásico. Esto se puede observar cuando comparamos el RMSE/MAE sobre train y test.

lm_vs_lm_models_validation(lineal_model_3, robust_lineal_model_3, train_set_with_outliers)
Warning in actual - predicted :
  longer object length is not a multiple of shorter object length
Warning in actual - predicted :
  longer object length is not a multiple of shorter object length
Warning in actual - predicted :
  longer object length is not a multiple of shorter object length
Warning in actual - predicted :
  longer object length is not a multiple of shorter object length
lm_vs_lm_models_validation(lineal_model_3, robust_lineal_model_3, test_set)

3. Modelo bayesiano con Likelihood normal

bayesion_model_3 <- stan(
  model_code =  "
    data {
      int<lower=1>               obs_count;
      vector<lower=1>[obs_count] x;
      vector[obs_count]          y;
    }
    parameters {
      real          beta0;
      real          beta1;
      real<lower=0> sigma;
    }
    model {
      // Distribuciones a priori (Fijado por el investigador)
      beta0 ~ normal(-6000, 500);  // Intercept (Muy informativa!!!)
      beta1 ~ normal(0, 100);      // flipper_length_mm (Muy informativa!!!)
      sigma ~ exponential(0.1);    // Varianza

      // Likelihood
      y ~ normal(beta0 + beta1 * x, sigma);
    }
  ",
  data = list(
      obs_count = nrow(train_set_with_outliers),
      x = colvalues(train_set_with_outliers, 'flipper_length_mm'),
      y = colvalues(train_set_with_outliers, 'body_mass_g')
  ),
  chains = 3,
  iter   = 1000,
  warmup = 300,
  thin   = 1
)
starting worker pid=29790 on localhost:11799 at 00:03:56.670
starting worker pid=29827 on localhost:11799 at 00:03:56.780
starting worker pid=29864 on localhost:11799 at 00:03:56.889

SAMPLING FOR MODEL '4c854be188b76190ba259392f0cefe60' NOW (CHAIN 1).
Chain 1: 
Chain 1: Gradient evaluation took 1.7e-05 seconds
Chain 1: 1000 transitions using 10 leapfrog steps per transition would take 0.17 seconds.
Chain 1: Adjust your expectations accordingly!
Chain 1: 
Chain 1: 
Chain 1: Iteration:   1 / 1000 [  0%]  (Warmup)
Chain 1: Iteration: 100 / 1000 [ 10%]  (Warmup)
Chain 1: Iteration: 200 / 1000 [ 20%]  (Warmup)
Chain 1: Iteration: 300 / 1000 [ 30%]  (Warmup)
Chain 1: Iteration: 301 / 1000 [ 30%]  (Sampling)
Chain 1: Iteration: 400 / 1000 [ 40%]  (Sampling)
Chain 1: Iteration: 500 / 1000 [ 50%]  (Sampling)
Chain 1: Iteration: 600 / 1000 [ 60%]  (Sampling)
Chain 1: Iteration: 700 / 1000 [ 70%]  (Sampling)
Chain 1: Iteration: 800 / 1000 [ 80%]  (Sampling)
Chain 1: Iteration: 900 / 1000 [ 90%]  (Sampling)
Chain 1: Iteration: 1000 / 1000 [100%]  (Sampling)
Chain 1: 
Chain 1:  Elapsed Time: 0.242403 seconds (Warm-up)
Chain 1:                0.204858 seconds (Sampling)
Chain 1:                0.447261 seconds (Total)
Chain 1: 

SAMPLING FOR MODEL '4c854be188b76190ba259392f0cefe60' NOW (CHAIN 2).
Chain 2: 
Chain 2: Gradient evaluation took 1.8e-05 seconds
Chain 2: 1000 transitions using 10 leapfrog steps per transition would take 0.18 seconds.
Chain 2: Adjust your expectations accordingly!
Chain 2: 
Chain 2: 
Chain 2: Iteration:   1 / 1000 [  0%]  (Warmup)
Chain 2: Iteration: 100 / 1000 [ 10%]  (Warmup)
Chain 2: Iteration: 200 / 1000 [ 20%]  (Warmup)
Chain 2: Iteration: 300 / 1000 [ 30%]  (Warmup)
Chain 2: Iteration: 301 / 1000 [ 30%]  (Sampling)
Chain 2: Iteration: 400 / 1000 [ 40%]  (Sampling)
Chain 2: Iteration: 500 / 1000 [ 50%]  (Sampling)
Chain 2: Iteration: 600 / 1000 [ 60%]  (Sampling)
Chain 2: Iteration: 700 / 1000 [ 70%]  (Sampling)
Chain 2: Iteration: 800 / 1000 [ 80%]  (Sampling)
Chain 2: Iteration: 900 / 1000 [ 90%]  (Sampling)
Chain 2: Iteration: 1000 / 1000 [100%]  (Sampling)
Chain 2: 
Chain 2:  Elapsed Time: 0.231599 seconds (Warm-up)
Chain 2:                0.248663 seconds (Sampling)
Chain 2:                0.480262 seconds (Total)
Chain 2: 

SAMPLING FOR MODEL '4c854be188b76190ba259392f0cefe60' NOW (CHAIN 3).
Chain 3: 
Chain 3: Gradient evaluation took 2e-05 seconds
Chain 3: 1000 transitions using 10 leapfrog steps per transition would take 0.2 seconds.
Chain 3: Adjust your expectations accordingly!
Chain 3: 
Chain 3: 
Chain 3: Iteration:   1 / 1000 [  0%]  (Warmup)
Chain 3: Iteration: 100 / 1000 [ 10%]  (Warmup)
Chain 3: Iteration: 200 / 1000 [ 20%]  (Warmup)
Chain 3: Iteration: 300 / 1000 [ 30%]  (Warmup)
Chain 3: Iteration: 301 / 1000 [ 30%]  (Sampling)
Chain 3: Iteration: 400 / 1000 [ 40%]  (Sampling)
Chain 3: Iteration: 500 / 1000 [ 50%]  (Sampling)
Chain 3: Iteration: 600 / 1000 [ 60%]  (Sampling)
Chain 3: Iteration: 700 / 1000 [ 70%]  (Sampling)
Chain 3: Iteration: 800 / 1000 [ 80%]  (Sampling)
Chain 3: Iteration: 900 / 1000 [ 90%]  (Sampling)
Chain 3: Iteration: 1000 / 1000 [100%]  (Sampling)
Chain 3: 
Chain 3:  Elapsed Time: 0.13834 seconds (Warm-up)
Chain 3:                0.227717 seconds (Sampling)
Chain 3:                0.366057 seconds (Total)
Chain 3: 
params_3 <- c('beta0', 'beta1', 'sigma')
traceplot(bayesion_model_3, pars = params_3, inc_warmup = TRUE)

4. Coeficientes

lm_vs_br_coeficients(robust_lineal_model_3, bayesion_model_3, params_3)

5. Validación

vars_3 <- c('flipper_length_mm') 

lm_vs_br_models_validation(robust_lineal_model_3, bayesion_model_3, params_3, vars_3, test_set)
bayesion_predictor_3 <- BayesianRegressionPredictor.from(bayesion_model_3, params_3, vars_3)

plot_compare_fit(
  robust_lineal_model_3, 
  bayesion_predictor_3, 
  train_set,
  label_1='Regresion Lineal Robusta CON outliers', 
  label_2='Regresion Bayesiana CON outliers'
)

6. Modelo bayesiano con Likelihood t-student

bayesion_model_3.1 <- stan(
  model_code =  "
    data {
      int<lower=1>               obs_count;
      vector<lower=1>[obs_count] x;
      vector[obs_count]          y;
    }
    parameters {
      real          beta0;
      real          beta1;
      real<lower=0> sigma;
    }
    model {
      // Distribuciones a priori (Fijado por el investigador)
      beta0 ~ normal(-5700, 50);  // Intercept (Muy informativa!!!)
      beta1 ~ normal(49, 20);      // flipper_length_mm (Muy informativa!!!)
      sigma ~ exponential(0.1); // Varianza

      // Likelihood
      y ~ student_t(2, beta0 + beta1 * x, sigma);
    }
  ",
  data = list(
      obs_count = nrow(train_set_with_outliers),
      x = colvalues(train_set_with_outliers, 'flipper_length_mm'),
      y = colvalues(train_set_with_outliers, 'body_mass_g')
  ),
  chains = 3,
  iter   = 1000,
  warmup = 300,
  thin   = 1
)
starting worker pid=30911 on localhost:11799 at 00:08:24.510
starting worker pid=30948 on localhost:11799 at 00:08:24.618
starting worker pid=30985 on localhost:11799 at 00:08:24.729

SAMPLING FOR MODEL '1675203fd35ad686882090462fa7c61a' NOW (CHAIN 1).
Chain 1: 
Chain 1: Gradient evaluation took 2.4e-05 seconds
Chain 1: 1000 transitions using 10 leapfrog steps per transition would take 0.24 seconds.
Chain 1: Adjust your expectations accordingly!
Chain 1: 
Chain 1: 
Chain 1: Iteration:   1 / 1000 [  0%]  (Warmup)
Chain 1: Iteration: 100 / 1000 [ 10%]  (Warmup)
Chain 1: Iteration: 200 / 1000 [ 20%]  (Warmup)
Chain 1: Iteration: 300 / 1000 [ 30%]  (Warmup)
Chain 1: Iteration: 301 / 1000 [ 30%]  (Sampling)
Chain 1: Iteration: 400 / 1000 [ 40%]  (Sampling)
Chain 1: Iteration: 500 / 1000 [ 50%]  (Sampling)
Chain 1: Iteration: 600 / 1000 [ 60%]  (Sampling)
Chain 1: Iteration: 700 / 1000 [ 70%]  (Sampling)
Chain 1: Iteration: 800 / 1000 [ 80%]  (Sampling)
Chain 1: Iteration: 900 / 1000 [ 90%]  (Sampling)
Chain 1: Iteration: 1000 / 1000 [100%]  (Sampling)
Chain 1: 
Chain 1:  Elapsed Time: 0.064665 seconds (Warm-up)
Chain 1:                0.099819 seconds (Sampling)
Chain 1:                0.164484 seconds (Total)
Chain 1: 

SAMPLING FOR MODEL '1675203fd35ad686882090462fa7c61a' NOW (CHAIN 2).
Chain 2: 
Chain 2: Gradient evaluation took 2.1e-05 seconds
Chain 2: 1000 transitions using 10 leapfrog steps per transition would take 0.21 seconds.
Chain 2: Adjust your expectations accordingly!
Chain 2: 
Chain 2: 
Chain 2: Iteration:   1 / 1000 [  0%]  (Warmup)
Chain 2: Iteration: 100 / 1000 [ 10%]  (Warmup)
Chain 2: Iteration: 200 / 1000 [ 20%]  (Warmup)
Chain 2: Iteration: 300 / 1000 [ 30%]  (Warmup)
Chain 2: Iteration: 301 / 1000 [ 30%]  (Sampling)
Chain 2: Iteration: 400 / 1000 [ 40%]  (Sampling)
Chain 2: Iteration: 500 / 1000 [ 50%]  (Sampling)
Chain 2: Iteration: 600 / 1000 [ 60%]  (Sampling)
Chain 2: Iteration: 700 / 1000 [ 70%]  (Sampling)
Chain 2: Iteration: 800 / 1000 [ 80%]  (Sampling)
Chain 2: Iteration: 900 / 1000 [ 90%]  (Sampling)
Chain 2: Iteration: 1000 / 1000 [100%]  (Sampling)
Chain 2: 
Chain 2:  Elapsed Time: 0.150916 seconds (Warm-up)
Chain 2:                0.094938 seconds (Sampling)
Chain 2:                0.245854 seconds (Total)
Chain 2: 

SAMPLING FOR MODEL '1675203fd35ad686882090462fa7c61a' NOW (CHAIN 3).
Chain 3: 
Chain 3: Gradient evaluation took 2.5e-05 seconds
Chain 3: 1000 transitions using 10 leapfrog steps per transition would take 0.25 seconds.
Chain 3: Adjust your expectations accordingly!
Chain 3: 
Chain 3: 
Chain 3: Iteration:   1 / 1000 [  0%]  (Warmup)
Chain 3: Iteration: 100 / 1000 [ 10%]  (Warmup)
Chain 3: Iteration: 200 / 1000 [ 20%]  (Warmup)
Chain 3: Iteration: 300 / 1000 [ 30%]  (Warmup)
Chain 3: Iteration: 301 / 1000 [ 30%]  (Sampling)
Chain 3: Iteration: 400 / 1000 [ 40%]  (Sampling)
Chain 3: Iteration: 500 / 1000 [ 50%]  (Sampling)
Chain 3: Iteration: 600 / 1000 [ 60%]  (Sampling)
Chain 3: Iteration: 700 / 1000 [ 70%]  (Sampling)
Chain 3: Iteration: 800 / 1000 [ 80%]  (Sampling)
Chain 3: Iteration: 900 / 1000 [ 90%]  (Sampling)
Chain 3: Iteration: 1000 / 1000 [100%]  (Sampling)
Chain 3: 
Chain 3:  Elapsed Time: 0.119479 seconds (Warm-up)
Chain 3:                0.081591 seconds (Sampling)
Chain 3:                0.20107 seconds (Total)
Chain 3: 
params_3 <- c('beta0', 'beta1', 'sigma')
traceplot(bayesion_model_3.1, pars = params_3, inc_warmup = TRUE)

7. Coeficientes

lm_vs_br_coeficients(lineal_model_1, bayesion_model_3.1, params_3)

8. Validación

vars_3 <- c('flipper_length_mm') 

lm_vs_br_models_validation(lineal_model_1, bayesion_model_3.1, params_3, vars_3, test_set)
bayesion_predictor_3.1 <- BayesianRegressionPredictor.from(bayesion_model_3.1, params_3, vars_3)

plot_compare_fit(
  lineal_model_1, 
  bayesion_predictor_3.1, 
  train_set_with_outliers,
  label_1='Regresion Lineal SIN outliers', 
  label_2='Regresion Bayesiana CON outliers'
)

Experimento 4

  • Idem experimento 1 pero reduciendo la cantidad de observaciones a pocos valores (ej:30).
  • Regresión múltiple frecuentista.
  • Regresión bayesiana con priors normales y exponencial.

1. Split train - test

En este aso entrenamos solo con el 10% de lo datos.

train_test <- train_test_split(dataset, train_size = 0.05, shuffle = TRUE)
[1] "Train set size: 16"
[1] "Test set size: 317"
train_set_4 <- train_test[[1]]
test_set_4  <- train_test[[2]]
plot_data(train_set_4)

2. Modelo lineal

lineal_model_4 <- lm(
  body_mass_g ~ flipper_length_mm,
  data = train_set_4
)

3. Modelo bayesiano

bayesion_model_4 <- stan(
  model_code =  "
    data {
      int<lower=1>               obs_count;
      vector<lower=1>[obs_count] x;
      vector[obs_count]          y;
    }
    parameters {
      real          beta0;
      real          beta1;
      real<lower=0> sigma;
    }
    model {
      // Distribuciones a priori
      beta0 ~ normal(0, 8000); // Intercept
      beta1 ~ normal(0, 100);
      sigma ~ exponential(0.1);
    
      // Likelihood
      y ~ normal(beta0 + beta1 * x, sigma);
    }
  ",
  data = list(
      obs_count = nrow(train_set_4),
      x = colvalues(train_set_4, 'flipper_length_mm'),
      y  = colvalues(train_set_4, 'body_mass_g')
  ),
  chains = 3,
  iter   = 300,
  warmup = 180,
  thin   = 1
)
starting worker pid=31466 on localhost:11799 at 00:15:59.730
starting worker pid=31503 on localhost:11799 at 00:15:59.838
starting worker pid=31540 on localhost:11799 at 00:15:59.948

SAMPLING FOR MODEL 'c4d62a81dae11941a9914c2e1cae7316' NOW (CHAIN 1).
Chain 1: 
Chain 1: Gradient evaluation took 1.2e-05 seconds
Chain 1: 1000 transitions using 10 leapfrog steps per transition would take 0.12 seconds.
Chain 1: Adjust your expectations accordingly!
Chain 1: 
Chain 1: 
Chain 1: Iteration:   1 / 300 [  0%]  (Warmup)
Chain 1: Iteration:  30 / 300 [ 10%]  (Warmup)
Chain 1: Iteration:  60 / 300 [ 20%]  (Warmup)
Chain 1: Iteration:  90 / 300 [ 30%]  (Warmup)
Chain 1: Iteration: 120 / 300 [ 40%]  (Warmup)
Chain 1: Iteration: 150 / 300 [ 50%]  (Warmup)
Chain 1: Iteration: 180 / 300 [ 60%]  (Warmup)
Chain 1: Iteration: 181 / 300 [ 60%]  (Sampling)
Chain 1: Iteration: 210 / 300 [ 70%]  (Sampling)
Chain 1: Iteration: 240 / 300 [ 80%]  (Sampling)
Chain 1: Iteration: 270 / 300 [ 90%]  (Sampling)
Chain 1: Iteration: 300 / 300 [100%]  (Sampling)
Chain 1: 
Chain 1:  Elapsed Time: 0.03853 seconds (Warm-up)
Chain 1:                0.010174 seconds (Sampling)
Chain 1:                0.048704 seconds (Total)
Chain 1: 

SAMPLING FOR MODEL 'c4d62a81dae11941a9914c2e1cae7316' NOW (CHAIN 2).
Chain 2: 
Chain 2: Gradient evaluation took 9e-06 seconds
Chain 2: 1000 transitions using 10 leapfrog steps per transition would take 0.09 seconds.
Chain 2: Adjust your expectations accordingly!
Chain 2: 
Chain 2: 
Chain 2: Iteration:   1 / 300 [  0%]  (Warmup)
Chain 2: Iteration:  30 / 300 [ 10%]  (Warmup)
Chain 2: Iteration:  60 / 300 [ 20%]  (Warmup)
Chain 2: Iteration:  90 / 300 [ 30%]  (Warmup)
Chain 2: Iteration: 120 / 300 [ 40%]  (Warmup)
Chain 2: Iteration: 150 / 300 [ 50%]  (Warmup)
Chain 2: Iteration: 180 / 300 [ 60%]  (Warmup)
Chain 2: Iteration: 181 / 300 [ 60%]  (Sampling)
Chain 2: Iteration: 210 / 300 [ 70%]  (Sampling)
Chain 2: Iteration: 240 / 300 [ 80%]  (Sampling)
Chain 2: Iteration: 270 / 300 [ 90%]  (Sampling)
Chain 2: Iteration: 300 / 300 [100%]  (Sampling)
Chain 2: 
Chain 2:  Elapsed Time: 0.051002 seconds (Warm-up)
Chain 2:                0.013484 seconds (Sampling)
Chain 2:                0.064486 seconds (Total)
Chain 2: 

SAMPLING FOR MODEL 'c4d62a81dae11941a9914c2e1cae7316' NOW (CHAIN 3).
Chain 3: 
Chain 3: Gradient evaluation took 8e-06 seconds
Chain 3: 1000 transitions using 10 leapfrog steps per transition would take 0.08 seconds.
Chain 3: Adjust your expectations accordingly!
Chain 3: 
Chain 3: 
Chain 3: Iteration:   1 / 300 [  0%]  (Warmup)
Chain 3: Iteration:  30 / 300 [ 10%]  (Warmup)
Chain 3: Iteration:  60 / 300 [ 20%]  (Warmup)
Chain 3: Iteration:  90 / 300 [ 30%]  (Warmup)
Chain 3: Iteration: 120 / 300 [ 40%]  (Warmup)
Chain 3: Iteration: 150 / 300 [ 50%]  (Warmup)
Chain 3: Iteration: 180 / 300 [ 60%]  (Warmup)
Chain 3: Iteration: 181 / 300 [ 60%]  (Sampling)
Chain 3: Iteration: 210 / 300 [ 70%]  (Sampling)
Chain 3: Iteration: 240 / 300 [ 80%]  (Sampling)
Chain 3: Iteration: 270 / 300 [ 90%]  (Sampling)
Chain 3: Iteration: 300 / 300 [100%]  (Sampling)
Chain 3: 
Chain 3:  Elapsed Time: 0.054605 seconds (Warm-up)
Chain 3:                0.010649 seconds (Sampling)
Chain 3:                0.065254 seconds (Total)
Chain 3: 
params_4 <- c('beta0', 'beta1', 'sigma')
traceplot(bayesion_model_4, pars = params_4, inc_warmup = TRUE)

4. Coeficientes

Coeficientes de la regresión múltiple:

lineal_model_4$coefficients
      (Intercept) flipper_length_mm 
      -4668.30188          44.28301 

Coeficientes descubiertos por la regresión múltiple bayesiana:

for(param in params_4) print(get_posterior_mean(bayesion_model_4, par=param)[4])
[1] -4464.407
[1] 43.26266
[1] 261.9534

5. Validación

vars_4 <- c('flipper_length_mm') 

lm_vs_br_models_validation(lineal_model_4, bayesion_model_4, params_4, vars_4, test_set)
bayesion_predictor_4 <- BayesianRegressionPredictor.from(bayesion_model_4, params_4, vars_4)

plot_compare_fit(
  lineal_model_4,
  bayesion_predictor_4, 
  train_set,
  label_1='Regresion Lineal', 
  label_2='Regresion Bayesiana'
)

Experimento 5

  • Igual al experimento 1 pero proponiendo dos nuevas regresiones bayesianas con priors para los parámetros que sean:
    • Una poca informativa (uniforme).
    • Una muy informativa (sesgada o con muy poca varianza).
  • Comparar con resultados de la bayesiana del experimento A

1. Modelo bayesiano con parametro con distribucion poco informativa

1. Modelo

Definimos una distribución uniforme para el beta asociado a la variable flipper_length_mm.

starting worker pid=31882 on localhost:11799 at 00:19:15.014
starting worker pid=31919 on localhost:11799 at 00:19:15.123
starting worker pid=31956 on localhost:11799 at 00:19:15.233

SAMPLING FOR MODEL '776b18360e3917d6e2282a204c6c0960' NOW (CHAIN 1).
Chain 1: 
Chain 1: Gradient evaluation took 1.6e-05 seconds
Chain 1: 1000 transitions using 10 leapfrog steps per transition would take 0.16 seconds.
Chain 1: Adjust your expectations accordingly!
Chain 1: 
Chain 1: 
Chain 1: Iteration:   1 / 1000 [  0%]  (Warmup)
Chain 1: Iteration: 100 / 1000 [ 10%]  (Warmup)
Chain 1: Iteration: 181 / 1000 [ 18%]  (Sampling)
Chain 1: Iteration: 280 / 1000 [ 28%]  (Sampling)
Chain 1: Iteration: 380 / 1000 [ 38%]  (Sampling)
Chain 1: Iteration: 480 / 1000 [ 48%]  (Sampling)
Chain 1: Iteration: 580 / 1000 [ 58%]  (Sampling)
Chain 1: Iteration: 680 / 1000 [ 68%]  (Sampling)
Chain 1: Iteration: 780 / 1000 [ 78%]  (Sampling)
Chain 1: Iteration: 880 / 1000 [ 88%]  (Sampling)
Chain 1: Iteration: 980 / 1000 [ 98%]  (Sampling)
Chain 1: Iteration: 1000 / 1000 [100%]  (Sampling)
Chain 1: 
Chain 1:  Elapsed Time: 0.154943 seconds (Warm-up)
Chain 1:                0.349263 seconds (Sampling)
Chain 1:                0.504206 seconds (Total)
Chain 1: 

SAMPLING FOR MODEL '776b18360e3917d6e2282a204c6c0960' NOW (CHAIN 2).
Chain 2: 
Chain 2: Gradient evaluation took 1.9e-05 seconds
Chain 2: 1000 transitions using 10 leapfrog steps per transition would take 0.19 seconds.
Chain 2: Adjust your expectations accordingly!
Chain 2: 
Chain 2: 
Chain 2: Iteration:   1 / 1000 [  0%]  (Warmup)
Chain 2: Iteration: 100 / 1000 [ 10%]  (Warmup)
Chain 2: Iteration: 181 / 1000 [ 18%]  (Sampling)
Chain 2: Iteration: 280 / 1000 [ 28%]  (Sampling)
Chain 2: Iteration: 380 / 1000 [ 38%]  (Sampling)
Chain 2: Iteration: 480 / 1000 [ 48%]  (Sampling)
Chain 2: Iteration: 580 / 1000 [ 58%]  (Sampling)
Chain 2: Iteration: 680 / 1000 [ 68%]  (Sampling)
Chain 2: Iteration: 780 / 1000 [ 78%]  (Sampling)
Chain 2: Iteration: 880 / 1000 [ 88%]  (Sampling)

SAMPLING FOR MODEL '776b18360e3917d6e2282a204c6c0960' NOW (CHAIN 3).
Chain 3: 
Chain 3: Gradient evaluation took 1.8e-05 seconds
Chain 3: 1000 transitions using 10 leapfrog steps per transition would take 0.18 seconds.
Chain 3: Adjust your expectations accordingly!
Chain 3: 
Chain 3: 
Chain 3: Iteration:   1 / 1000 [  0%]  (Warmup)
Chain 2: Iteration: 980 / 1000 [ 98%]  (Sampling)
Chain 2: Iteration: 1000 / 1000 [100%]  (Sampling)
Chain 2: 
Chain 2:  Elapsed Time: 0.16838 seconds (Warm-up)
Chain 2:                0.362988 seconds (Sampling)
Chain 2:                0.531368 seconds (Total)
Chain 2: 
Chain 3: Iteration: 100 / 1000 [ 10%]  (Warmup)
Chain 3: Iteration: 181 / 1000 [ 18%]  (Sampling)
Chain 3: Iteration: 280 / 1000 [ 28%]  (Sampling)
Chain 3: Iteration: 380 / 1000 [ 38%]  (Sampling)
Chain 3: Iteration: 480 / 1000 [ 48%]  (Sampling)
Chain 3: Iteration: 580 / 1000 [ 58%]  (Sampling)
Chain 3: Iteration: 680 / 1000 [ 68%]  (Sampling)
Chain 3: Iteration: 780 / 1000 [ 78%]  (Sampling)
Chain 3: Iteration: 880 / 1000 [ 88%]  (Sampling)
Chain 3: Iteration: 980 / 1000 [ 98%]  (Sampling)
Chain 3: Iteration: 1000 / 1000 [100%]  (Sampling)
Chain 3: 
Chain 3:  Elapsed Time: 0.137244 seconds (Warm-up)
Chain 3:                0.31702 seconds (Sampling)
Chain 3:                0.454264 seconds (Total)
Chain 3: 

2. Coeficientes

br_vs_br_coeficients(bayesion_model_1, bayesion_model_5, params_5)

3. Validación

lm_vs_br_models_validation(lineal_model_1, bayesion_model_1, params_1, vars_1, test_set)

4. Validacion

vars_5 <- c('flipper_length_mm') 

lm_vs_br_models_validation(lineal_model_1, bayesion_model_5, params_5, vars_5, test_set)
bayesion_predictor_5 <- BayesianRegressionPredictor.from(bayesion_model_5, params_5, vars_5)

plot_compare_fit(
  bayesion_predictor_1,
  bayesion_predictor_5,
  train_set,
  label_1='Regresion Bayesiana con dist informativa', 
  label_2='Regresion Bayesiana con dist menos informativa'
)

2. Modelo bayesiano con parametro con distribucion muy informativa sesgada o con poca varianza

COMPLETAR

LS0tCnRpdGxlOiAiRW5mb3F1ZSBFc3RhZGlzdGljbyBkZWwgQXByZW5kaXphamUgLSBUcmFiYWpvIEZpbmFsIC0gUmVncmVzaW9uIEJheWVzaWFuYSIKZmlnX3dpZHRoOiAzIApmaWdfaGVpZ2h0OiAzIApvdXRwdXQ6CiAgaHRtbF9kb2N1bWVudDoKICAgIGhpZ2hsaWdodDogcHlnbWVudHMKICAgIHRoZW1lOiBzYW5kc3RvbmUKICAgIHRvYzogeWVzCiAgICBkZl9wcmludDogcGFnZWQKICAgIGluY2x1ZGVzOgogICAgICBiZWZvcmVfYm9keTogLi9oZWFkZXIuaHRtbAogIGh0bWxfbm90ZWJvb2s6IAogICAgdG9jOiB5ZXMKICAgIHRvY19mbG9hdDogeWVzCiAgICBkZl9wcmludDogcGFnZWQKLS0tCgojIyMgQWRyaWFuIE1hcmlubwoKIyMjIENsYXVkaW8gQ29sbGFkbwoKCiMgSW5pY2lhbGl6YWNpw7NuCgpGaWphbW9zIGxhIHNlbWlsbGEgcGFyYSBwb2RlciByZXByb2R1Y2lyIGxvcyBleHBlcmltZW50b3MuIFRhbWJpw6luIHNlIGZpamEgZWwgbnVtZXJvIGRlIENQVSdzIGEgdXRpbGl6YXIuCgpgYGB7cn0Kc2V0LnNlZWQoNDIpCm9wdGlvbnMobWMuY29yZXMgPSAyNCkKYGBgCgoKIyBMaWJyZXJpYXMKClNlIGltcG9ydGFuIGxhcyBsaWJyZXLDrWFzIGEgdXRpbGl6YXIgYSBsbyBsYXJnbyBkZSBsYSBub3RlYm9vazoKCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CiMgaW5zdGFsbC5wYWNrYWdlcyhwYWNtYW4pCiMgaW5zdGFsbC5wYWNrYWdlcygiaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvc3JjL2NvbnRyaWIvcnN0YW5fMi4yMS4yLnRhci5neiIscmVwb3MgPSBOVUxMLHR5cGU9InNvdXJjZSIpCiMgc3VkbyBhcHQtZ2V0IGluc3RhbGwgbGliZ2xway1kZXYKYGBgCgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpsaWJyYXJ5KHBhY21hbikKcF9sb2FkKHRpZHl2ZXJzZSwgdGlkeW1vZGVscywgcnNhbXBsZSwgcnN0YW4sIHNoaW55c3RhbiwgcnN0YW5hcm0sIGRldnRvb2xzKQoKc291cmNlKCcuLi9zcmMvZGF0YXNldC5SJykKc291cmNlKCcuLi9zcmMvcGxvdC5SJykKc291cmNlKCcuLi9zcmMvbW9kZWwuUicpCmBgYAoKIyBEYXRhc2V0IHkgQW5hbGlzaXMgRXhwbG9yYXRvcmlvCgohW1BhbG1lciBQZW5ndWluc10oaHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL2FsbGlzb25ob3JzdC9wYWxtZXJwZW5ndWlucy9tYXN0ZXIvbWFuL2ZpZ3VyZXMvbHRlcl9wZW5ndWlucy5wbmcpCgpbUGFsbWVyIFBlbmd1aW5zXShodHRwczovL2dpdGh1Yi5jb20vcmZvcmRhdGFzY2llbmNlL3RpZHl0dWVzZGF5L2Jsb2IvbWFzdGVyL2RhdGEvMjAyMC8yMDIwLTA3LTI4L3JlYWRtZS5tZCkKCgojIyAxLiBMZWN0dXJhIGRlbCBkYXRhc2V0CgoKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KZGF0YXNldCA8LSBsb2FkX2RhdGFzZXQoKSAlPiUgbXV0YXRlX2lmKGlzLmNoYXJhY3RlciwgYXMuZmFjdG9yKQoKZGF0YXNldCAlPiUgZ2xpbXBzZSgpCmBgYAoKCiMjIDIuIFZhcmlhYmxlcwoKU2UgZW51bWVyYW4geSBkZXNjcmliZW4gYnJldmUtbWVudGUgY2FkYSB2YXJpYWJsZSBxdWUgZm9ybWEgcGFydGUgZGVsIGRhdGFzZXQ6CgpWYXJpYWJsZXMgTnVtw6lyaWNhczoKCiogKipiaWxsX2xlbmd0aF9tbSoqOiBMb25naXR1ZCBkZWwgcGljbyBkZWwgaW5kaXZpZHVvIG1lZGlkYSBlbiBtaWzDrW1ldHJvcyAodGFtYmnDqW4gY29ub2NpZGEgY29tbyBsb25naXR1ZCBkZWwgY3VsbWVuKS4KKiAqKmJpbGxfZGVwdGhfbW0qKjogUHJvZnVuZGlkYWQgZGVsIHBpY28gZGVsIGluZGl2aWR1byBtZWRpZGEgZW4gbWlsw61tZXRyb3MgKHRhbWJpw6luIGNvbm9jaWRhIGNvbW8gcHJvZnVuZGlkYWQgZGVsIGN1bG1lbikuCiogKipmbGlwcGVyX2xlbmd0aF9tbSoqOiBMb25naXR1ZCBkZSBsYSBhbGV0YSBkZWwgaW5kaXZpZHVvIG1lZGlkYSBlbiBtaWzDrW1ldHJvcy4KKiAqKmJvZHlfbWFzc19nKio6IE1hc2EgY29ycG9yYWwgZGVsIGluZGl2aWR1byBtZWRpZGEgZW4gZ3JhbW9zLgoqICoqeWVhcioqOiBBw7FvIGVuIGVsIHF1ZSBzZSByZWdpc3RyYSBlbCBpbmRpdmlkdW8uCgpWYXJpYWJsZXMgQ2F0ZWfDs3JpY2FzOgoKKiAqKnNwZWNpZXMqKjogRXNwZWNpZSBkZWwgaW5kaXZpZHVvIChBZGVsaWUsIEdlbnRvbyA7KSBvIENoaW5zdHJhcCkuCiogKipzZXgqKjogU2V4byBkZWwgaW5kaXZpZHVvLgoqICoqaXNsYW5kKio6IElzbGEgZG9uZGUgc2UgZW5jb250csOpIGVsIGluZGl2aWR1byAoQmlzY29lLCBEcmVhbSBvIFRvcmdlcnNlbikuCgoKIyMgMy4gUmVzdW1lbiBkZSBmYWx0YW50ZXMKCmBgYHtyIG1lc3NhZ2U9RkFMU0Usd2FybmluZz1GQUxTRX0KbWlzc2luZ3Nfc3VtbWFyeShkYXRhc2V0KQpgYGAKCiMjIDQuIFZhcmlibGVzIG51bWVyaWNhcwoKYGBge3IgZmlnLmhlaWdodD0yLCBmaWcud2lkdGg9MywgbWVzc2FnZT1UUlVFLCB3YXJuaW5nPUZBTFNFfQpoaXN0X3Bsb3RzKGRhdGFzZXQpCmBgYAoKCioqT2JzZXJ2YWNpb25lcyoqCgoqIFNlIGFwcmVjaWEgcXVlIGNhZGEgYcOxbyBzZSByZWdpc3RybyBwcsOhY3RpY2FtZW50ZSBlbCBtaXNtbyBudW1lcm8gZGUgaW5kaXZpZHVvcy4KKiBMYSBkaXN0cmlidWNpw7NuIGRlIGxhIG1hc2EgY29ycG9yYWwgZGUgbG9zIGluZGl2aWR1b3MgdGllbmUgdW5hIGFzaW3DqXRyaWNhIHBvc2l0aXZhLiBUZW5lbW9zIG11Y2hvcyBpbmRpdmlkdW9zIGNvbiB2YWxvcmVzIGJham9zIGRlIG1hc2EgY29ycG9yYWwsIGNvbiB1bmEgbWVkaWEgZGUgMTkyIGdyYW1vcy4gTHVlZ28gdGVuZW1vcyBtZW5vcyBpbmRpdmlkdW9zIGNvbiB2YWxvcmVzIG1hcyBhbHRvLgoqIExhIGxvbmdpdHVkIGRlIGxhIGFsZXRhIHBhcmVjZSBzZXIgdW5hIGRpc3RyaWJ1Y2nDs24gYmktbW9kYWwuIFRlbmVtb3MgZG9zIG1vZGFzIHVuYSAxOTIgbW0geSBvdHJhIGVuIDIxNSBtbS4KKiBMYSBsb25naXR1ZCBkZWwgcGljbyB0YW1iacOpbiBwYXJlY2UgdGVuZXIgdW5hIGxpZ2VyYSBzaW1ldHLDrWEgcG9zaXRpdmEuIEVzIGRlY2lyIHF1ZSBsbyBpbmRpdmlkdW9zIGNvbiBtZW5vciBwZXNvIHRpZW5lIHBpY28gbWFzIHBlcXVlw7Fvcy4KKiBQb3Igb3RybyBsYWRvIGxhIHByb2Z1bmRpZGFkIGRlIHBpY28gcGFyZWNlIHRlbmVyIHVuYSBsaWdlcmEgc2ltZXRyw61hIHBvc2l0aXZhLgoKCmBgYHtyIGZpZy5hbGlnbj0nY2VudGVyJywgZmlnLmhlaWdodD01LCBmaWcud2lkdGg9OCwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgZmlnLmFsaWduPSdjZW50ZXInfQpib3hfcGxvdHMoZGF0YXNldCkKYGBgCgoKKipPYnNlcnZhY2lvbmVzKioKCiogQ09NUExFVEFSCgoKIyMjIE91dGxpZXJzCgpObyBzZSByZWdpc3RyYW4gdmFsb3JlcyBtYXMgZXh0cmVtb3MgcXVlIGVsIG3DrW5pbW8geSBtw6F4aW1vIHZhbG9yIGVuIGNhZGEgdmFyaWFibGVzLiBFcyBkZWNpciBxdWUgbm8gZW5jb250cmFtb3Mgb3V0bGllcnMuCgpgYGB7ciwgZmlnLnNob3c9J2hpZGUnfQpvdXRsaWVycyhkYXRhc2V0LCBjb2x1bW49J2JpbGxfbGVuZ3RoX21tJykKYGBgCgoKYGBge3IsIGZpZy5zaG93PSdoaWRlJ30Kb3V0bGllcnMoZGF0YXNldCwgY29sdW1uPSdiaWxsX2xlbmd0aF9tbScpCmBgYAoKCmBgYHtyLCBmaWcuc2hvdz0naGlkZSd9Cm91dGxpZXJzKGRhdGFzZXQsIGNvbHVtbj0nYmlsbF9kZXB0aF9tbScpCmBgYAoKYGBge3IsIGZpZy5zaG93PSdoaWRlJ30Kb3V0bGllcnMoZGF0YXNldCwgY29sdW1uPSdmbGlwcGVyX2xlbmd0aF9tbScpCmBgYAoKYGBge3IsIGZpZy5zaG93PSdoaWRlJ30Kb3V0bGllcnMoZGF0YXNldCwgY29sdW1uPSdib2R5X21hc3NfZycpCmBgYAoKCmBgYHtyLCBmaWcuc2hvdz0naGlkZSd9Cm91dGxpZXJzKGRhdGFzZXQsIGNvbHVtbj0neWVhcicpCmBgYAoKCmBgYHtyIGZpZy5oZWlnaHQ9MywgZmlnLndpZHRoPTMsIHdhcm5pbmc9RkFMU0V9CmJhcl9wbG90cyhkYXRhc2V0KQpgYGAKCioqT2JzZXJ2YWNpb25lcyoqCgoqIExhIHZhcmlhYmxlIHNleG8gc2UgZW5jdWVudHJhIGJhbGFuY2VhZGEuIFBvciBvdHJvIGxhZG8sIGNvbnRpZW5lIGFsZ3Vub3MgdmFsb3JlcyBmYWx0YW50ZXMuCiogTGEgdmFyaWFibGUgaXNsYW5kIGVzdGEgY29tcGxldGFtZW50ZSBkZXNiYWxhbmNlYWRhLiBFc3RvIHNlZ3VyYW1lbnRlIHNlIGRlYmUgYSB1bmEgZGlmZXJlbmNpYSBlbiBudW1lcm8KZW4gbGFzIHBvYmxhY2lvbmVzIGVuIGNhZGEgaXNsYSBvIGEgdW4gc2VzZ28gYWwgbW9tZW50byBkZSByZWdpc3RyYXIgbG9zIGluZGl2aWR1b3MuIEVzIGRlY2lyIHF1ZSByZWdpc3RyYW1vcyBjb24gaW5kaXZpZHVvcyBlbiB1bmEgaXNsYSBxdWUgZW4gb3RyYS4KKiBMbyBtaXNtbyBzdWNlZGUgY29uIGxhcyBlc3BlY2llcyBkZSBpbmRpdmlkdW9zLiBWZW1vcyB1biBncmFuIGRlc2JhbGFuY2UgZW50cmUgbGEgZXNwZWNpZSBDaGluc3RyYXAgdnMuIG90cmEgZXNwZWNpZXMuIFBvciBvdHJvIGFsZG8gQWRlbGllIHkgR2VudG9vIHRpZW5lIHVuIGNvbnRlbyBtYXMgY2VyY2FubwoKCiMjIDUuIEV4Y2x1aXIgb2JzZXJ2YWNpb25lcyBjb24gbWlzc2luZ3MKCmBgYHtyfQpkYXRhc2V0IDwtIGRhdGFzZXQgJT4lIGRyb3BfbmEoKQptaXNzaW5nc19zdW1tYXJ5KGRhdGFzZXQpCmBgYAoKIyMgNi4gQ29ycmVsYWNpb25lcwoKYGBge3IgZmlnLmFsaWduPSdjZW50ZXInLCBmaWcuaGVpZ2h0PTUsIGZpZy53aWR0aD01LCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBmaWcuYWxpZ249J2NlbnRlcid9CmNvcnJfcGxvdChkYXRhc2V0ICU+JSBkcGx5cjo6c2VsZWN0KC15ZWFyKSkKYGBgCgpgYGB7ciBmaWcuYWxpZ249J2NlbnRlcicsIGZpZy5oZWlnaHQ9MTIsIGZpZy53aWR0aD0xMiwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgZmlnLmFsaWduPSdjZW50ZXInfQpzZWdtZW50ZWRfcGFpcnNfcGxvdChkYXRhc2V0LCBzZWdtZW50X2NvbHVtbj0nc3BlY2llcycpCmBgYAoKIyBFeHBlcmltZW50b3MKCiMjIEV4cGVyaW1lbnRvIDEKCiogU29sbyB2YXJpYWJsZXMgbnVtw6lyaWNhcy4KKiBSZWdyZXNpw7NuIG3Dumx0aXBsZSBmcmVjdWVudGlzdGEuCiogUmVncmVzacOzbiBtw7psdGlwbGUgYmF5ZXNpYW5hIGNvbiBwcmlvcnMgbm9ybWFsZXMgeSBleHBvbmVuY2lhbC4KCgojIyMgMS4gU3BsaXQgdHJhaW4gdnMuIHRlc3QKCgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQp0cmFpbl90ZXN0IDwtIHRyYWluX3Rlc3Rfc3BsaXQoZGF0YXNldCwgdHJhaW5fc2l6ZSA9IDAuNywgc2h1ZmZsZSA9IFRSVUUpCnRyYWluX3NldCA8LSB0cmFpbl90ZXN0W1sxXV0KdGVzdF9zZXQgIDwtIHRyYWluX3Rlc3RbWzJdXQpgYGAKCgojIyMgMi4gTW9kZWxvIGxpbmVhbAoKYGBge3J9CmxpbmVhbF9tb2RlbF8xIDwtIGxtKAogIGJvZHlfbWFzc19nIH4gYmlsbF9sZW5ndGhfbW0gKyBiaWxsX2RlcHRoX21tICsgZmxpcHBlcl9sZW5ndGhfbW0sCiAgZGF0YSA9IHRyYWluX3NldAopCgpzdW1tYXJ5KGxpbmVhbF9tb2RlbF8xKQpgYGAKClF1aXRhbW9zIGxvcyBjb2VmaWNpZW50ZXMgcXVlIG5vIHNvbiBzaWduaWZpY2F0aXZvcyBwYXJhIGV4cGxpY2FyIGEgbGEgdmFyaWFibGUgKipib2R5X21hc3NfZyoqOgoKYGBge3J9CmxpbmVhbF9tb2RlbF8xIDwtIGxtKGJvZHlfbWFzc19nIH4gZmxpcHBlcl9sZW5ndGhfbW0sIGRhdGEgPSB0cmFpbl9zZXQpCgpzdW1tYXJ5KGxpbmVhbF9tb2RlbF8xKQpgYGAKCgojIyMgMy4gTW9kZWxvIGJheWVzaWFubwoKYGBge3IgZmlnLmFsaWduPSdjZW50ZXInLCBmaWcuaGVpZ2h0PTQsIGZpZy53aWR0aD04LCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBmaWcuYWxpZ249J2NlbnRlcid9CmJheWVzaW9uX21vZGVsXzEgPC0gc3RhbigKICBtb2RlbF9jb2RlID0gICIKICAgIGRhdGEgewogICAgICBpbnQ8bG93ZXI9MT4gICAgICAgICAgICAgICBvYnNfY291bnQ7CiAgICAgIHZlY3Rvcjxsb3dlcj0xPltvYnNfY291bnRdIHg7CiAgICAgIHZlY3RvcltvYnNfY291bnRdICAgICAgICAgIHk7CiAgICB9CiAgICBwYXJhbWV0ZXJzIHsKICAgICAgcmVhbCAgICAgICAgICBiZXRhMDsKICAgICAgcmVhbCAgICAgICAgICBiZXRhMTsKICAgICAgcmVhbDxsb3dlcj0wPiBzaWdtYTsKICAgIH0KICAgIG1vZGVsIHsKICAgICAgLy8gRGlzdHJpYnVjaW9uZXMgYSBwcmlvcmkgKEZpamFkbyBwb3IgZWwgaW52ZXN0aWdhZG9yKQogICAgICBiZXRhMCB+IG5vcm1hbCgwLCA4MDAwKTsgIC8vIEludGVyY2VwdAogICAgICBiZXRhMSB+IG5vcm1hbCgwLCAxMDApOyAgIC8vIGZsaXBwZXJfbGVuZ3RoX21tCiAgICAgIHNpZ21hIH4gZXhwb25lbnRpYWwoMC4xKTsgLy8gVmFyaWFuemEKCiAgICAgIC8vIExpa2VsaWhvb2QKICAgICAgeSB+IG5vcm1hbChiZXRhMCArIGJldGExICogeCwgc2lnbWEpOwogICAgfQogICIsCiAgZGF0YSA9IGxpc3QoCiAgICAgIG9ic19jb3VudCA9IG5yb3codHJhaW5fc2V0KSwKICAgICAgeCAgICAgICAgID0gY29sdmFsdWVzKHRyYWluX3NldCwgJ2ZsaXBwZXJfbGVuZ3RoX21tJyksCiAgICAgIHkgICAgICAgICA9IGNvbHZhbHVlcyh0cmFpbl9zZXQsICdib2R5X21hc3NfZycpCiAgKSwKICBjaGFpbnMgPSAzLAogIGl0ZXIgICA9IDMwMCwKICB3YXJtdXAgPSAxODAsCiAgdGhpbiAgID0gMQopCgpwYXJhbXNfMSA8LSBjKCdiZXRhMCcsICdiZXRhMScsICdzaWdtYScpCnRyYWNlcGxvdChiYXllc2lvbl9tb2RlbF8xLCBwYXJzID0gcGFyYW1zXzEsIGluY193YXJtdXAgPSBUUlVFKQpgYGAKCgojIyMgNC4gQ29lZmljaWVudGVzCgpgYGB7cn0KbG1fdnNfYnJfY29lZmljaWVudHMobGluZWFsX21vZGVsXzEsIGJheWVzaW9uX21vZGVsXzEsIHBhcmFtc18xKQpgYGAKCiMjIyA0LiBWYWxpZGFjacOzbgoKCmBgYHtyfQp2YXJzXzEgPC0gYygnZmxpcHBlcl9sZW5ndGhfbW0nKSAKCmxtX3ZzX2JyX21vZGVsc192YWxpZGF0aW9uKGxpbmVhbF9tb2RlbF8xLCBiYXllc2lvbl9tb2RlbF8xLCBwYXJhbXNfMSwgdmFyc18xLCB0ZXN0X3NldCkKYGBgCgpgYGB7ciBmaWcuYWxpZ249J2NlbnRlcicsIGZpZy5oZWlnaHQ9MywgZmlnLndpZHRoPTgsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGZpZy5hbGlnbj0nY2VudGVyJ30KYmF5ZXNpb25fcHJlZGljdG9yXzEgPC0gQmF5ZXNpYW5SZWdyZXNzaW9uUHJlZGljdG9yLmZyb20oYmF5ZXNpb25fbW9kZWxfMSwgcGFyYW1zXzEsIHZhcnNfMSkKCnBsb3RfY29tcGFyZV9maXQoCiAgbGluZWFsX21vZGVsXzEsIAogIGJheWVzaW9uX3ByZWRpY3Rvcl8xLCAKICB0cmFpbl9zZXQsCiAgbGFiZWxfMSA9ICdSZWdyZXNpb24gTGluZWFsJywgCiAgbGFiZWxfMiA9ICdSZWdyZXNpb24gQmF5ZXNpYW5hJwopCmBgYAoKCiMjIEV4cGVyaW1lbnRvIDIKCiogSWRlbSBhIGV4cGVyaW1lbnRvIDEsIGluY29ycG9yYW5kbyB1bmEgdmFyaWFibGUgY2F0ZWfDs3JpY2EuCiogUmVncmVzacOzbiBtw7psdGlwbGUgZnJlY3VlbnRpc3RhLgoqIFJlZ3Jlc2nDs24gYmF5ZXNpYW5hIGNvbiBwcmlvcnMgbm9ybWFsZXMgeSBleHBvbmVuY2lhbC4KCgojIyMgMS4gTW9kZWxvIGxpbmVhbAoKCmBgYHtyfQpsaW5lYWxfbW9kZWxfMiA8LSBsbSgKICAgIGJvZHlfbWFzc19nIAogICAgICB+IGJpbGxfbGVuZ3RoX21tCiAgICAgICsgYmlsbF9kZXB0aF9tbQogICAgICArIGZsaXBwZXJfbGVuZ3RoX21tCiAgICAgICsgc2V4LAoKICBkYXRhID0gdHJhaW5fc2V0CikKCnN1bW1hcnkobGluZWFsX21vZGVsXzIpCmBgYAoKUXVpdGFtb3MgbG9zIGNvZWZpY2llbnRlcyBxdWUgbm8gc29uIHNpZ25pZmljYXRpdm9zIHBhcmEgZXhwbGljYXIgYSBsYSB2YXJpYWJsZSAqKmJvZHlfbWFzc19nKio6CgpgYGB7cn0KbGluZWFsX21vZGVsXzIgPC0gbG0oCiAgICBib2R5X21hc3NfZyAKICAgICAgfiBiaWxsX2RlcHRoX21tCiAgICAgICsgZmxpcHBlcl9sZW5ndGhfbW0KICAgICAgKyBzZXgsCiAgZGF0YSA9IHRyYWluX3NldAopCgpzdW1tYXJ5KGxpbmVhbF9tb2RlbF8yKQpgYGAKCiMjIyAyLiAgTW9kZWxvIGJheWVzaWFubwoKQ29uc3RydWltb3MgdW5hIG1hdHJpeiBjb24gdG9kYXMgbGFzIHZhcmlhYmxlcyhYKSBtYXMgZWwgaW50ZXJjZXB0OgoKYGBge3J9CnRvX21vZGVsX2lucHV0IDwtIGZ1bmN0aW9uKGRmKSB7CiAgbW9kZWwubWF0cml4KAogICAgYm9keV9tYXNzX2cgCiAgICAgIH4gYmlsbF9kZXB0aF9tbQogICAgICArIGZsaXBwZXJfbGVuZ3RoX21tCiAgICAgICsgc2V4LAogICAgZGF0YSA9IGRmCiAgKQp9Cgp0cmFpbl9YIDwtIHRyYWluX3NldCAlPiUgdG9fbW9kZWxfaW5wdXQoKQp0ZXN0X1ggIDwtIHRlc3Rfc2V0ICU+JSB0b19tb2RlbF9pbnB1dCgpCgpoZWFkKHRyYWluX1gpCmBgYAoKCkRlZmluaW1vcyB5IGNvcnJlbW9zIGVsIG1vZGVsbyBiYXllc2lhbm86CgpgYGB7ciBmaWcuYWxpZ249J2NlbnRlcicsIGZpZy5oZWlnaHQ9NCwgZmlnLndpZHRoPTgsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGZpZy5hbGlnbj0nY2VudGVyJ30KYmF5ZXNpb25fbW9kZWxfMiA8LSBzdGFuKAogIG1vZGVsX2NvZGUgPSAiCiAgICBkYXRhIHsKICAgICAgaW50PGxvd2VyPTE+ICAgICAgICAgICAgICAgICBvYnNfY291bnQ7CiAgICAgIGludDxsb3dlcj0xPiAgICAgICAgICAgICAgICAgY29lZl9jb3VudDsKICAgICAgbWF0cml4W29ic19jb3VudCxjb2VmX2NvdW50XSBYOwogICAgICB2ZWN0b3Jbb2JzX2NvdW50XSAgICAgICAgICAgIHk7CiAgICB9CiAgICBwYXJhbWV0ZXJzIHsKICAgICAgdmVjdG9yW2NvZWZfY291bnRdICBiZXRhOwogICAgICByZWFsPGxvd2VyPTA+ICAgICAgIHNpZ21hOwogICAgfQogICAgbW9kZWwgewogICAgICAvLyBEaXN0cmlidWNpb25lcyBhIHByaW9yaQogICAgICBiZXRhWzFdIH4gbm9ybWFsKDAsIDMwMDApOyAvLyBJbnRlY2VwdCA9IGJldGEwICsgc2V4ZmVtYWxlCiAgICAgIGJldGFbMl0gfiBub3JtYWwoMCwgMjAwKTsgIC8vIGJpbGxfZGVwdGhfbW0KICAgICAgYmV0YVszXSB+IG5vcm1hbCgwLCAyMDApOyAgLy8gZmxpcHBlcl9sZW5ndGhfbW0KICAgICAgYmV0YVs0XSB+IG5vcm1hbCgwLCA2MDApOyAgLy8gc2V4bWFsZQogIAogICAgICBzaWdtYSB+IGV4cG9uZW50aWFsKDAuMSk7ICAvLyBWYXJpYW56YQogIAogICAgICAvLyBMaWtlbGlob29kCiAgICAgIHkgfiBub3JtYWwoWCAqIGJldGEsIHNpZ21hKTsKICAgIH0KICAiLAogIGRhdGEgPSBsaXN0KAogICAgICBvYnNfY291bnQgID0gZGltKHRyYWluX1gpWzFdLAogICAgICBjb2VmX2NvdW50ID0gZGltKHRyYWluX1gpWzJdLAogICAgICB5ICAgICAgICAgID0gY29sdmFsdWVzKHRyYWluX3NldCwgJ2JvZHlfbWFzc19nJyksCiAgICAgIFggICAgICAgICAgPSB0cmFpbl9YCiAgKSwKICBjaGFpbnMgPSAzLAogIGl0ZXIgICA9IDQwMDAsCiAgd2FybXVwID0gNTAwLAogIHRoaW4gICA9IDEKKQoKcGFyYW1zXzIgPC0gYygnYmV0YVsxXScsICdiZXRhWzJdJywgJ2JldGFbM10nLCAnYmV0YVs0XScsICdzaWdtYScpCnRyYWNlcGxvdChiYXllc2lvbl9tb2RlbF8yLCBpbmNfd2FybXVwID0gVFJVRSwgcGFycyA9IHBhcmFtc18yKQpgYGAKCgojIyMgMy4gQ29lZmljaWVudGVzCgpgYGB7cn0KbGluZWFsX21vZGVsXzIkY29lZmZpY2llbnRzCmBgYAoKYGBge3J9CmJyX2NvZWZpY2llbnRzKGJheWVzaW9uX21vZGVsXzIsIHBhcmFtc18yKQpgYGAKCiMjIyA0LiBWYWxpZGFjacOzbgoKYGBge3J9CnZhcnNfMiA8LSBjKCdiaWxsX2RlcHRoX21tJywgJ2ZsaXBwZXJfbGVuZ3RoX21tJywgJ3NleG1hbGUnKQoKbG1fdnNfYnJfbW9kZWxzX3ZhbGlkYXRpb24oCiAgbGluZWFsX21vZGVsXzIsIAogIGJheWVzaW9uX21vZGVsXzIsIAogIHBhcmFtc18yLAogIHZhcnNfMiwKICB0ZXN0X3NldCwKICBhcy5kYXRhLmZyYW1lKHRlc3RfWCkKKQpgYGAKCmBgYHtyIGZpZy5hbGlnbj0nY2VudGVyJywgZmlnLmhlaWdodD0zLCBmaWcud2lkdGg9OCwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgZmlnLmFsaWduPSdjZW50ZXInfQpiYXllc2lvbl9wcmVkaWN0b3JfMiA8LSBCYXllc2lhblJlZ3Jlc3Npb25QcmVkaWN0b3IuZnJvbShiYXllc2lvbl9tb2RlbF8yLCBwYXJhbXNfMiwgdmFyc18yKQoKcGxvdF9jb21wYXJlX2ZpdCgKICBsaW5lYWxfbW9kZWxfMiwgCiAgYmF5ZXNpb25fcHJlZGljdG9yXzIsIAogIHRlc3Rfc2V0LCAKICBhcy5kYXRhLmZyYW1lKHRlc3RfWCksCiAgbGFiZWxfMSA9ICdSZWdyZXNpb24gTGluZWFsJywgCiAgbGFiZWxfMiA9ICdSZWdyZXNpb24gQmF5ZXNpYW5hJwopCmBgYAoKCgoKIyMgRXhwZXJpbWVudG8gMwoKKiBJZGVtIGEgZXhwZXJpbWVudG8gMSBpbmNvcnBvcmFuZG8gb3V0bGllcnMgZW4gYWxndW5hIHZhcmlhYmxlIG51bcOpcmljYS4KKiBSZWdyZXNpw7NuIG3Dumx0aXBsZSBmcmVjdWVudGlzdGEuCiogUmVncmVzacOzbiBiYXllc2lhbmEgY29uIHByaW9ycyBub3JtYWxlcyB5IGV4cG9uZW5jaWFsLgoKCiMjIyAxLiBPdXRsaWVycwoKQSBjb250aW51YWNpw7NuIHZhbW9zIGEgYWdyZWdhciBvdXRsaWVycyBhIGxhIHZhcmlhYmxlICoqZmxpcHBlcl9sZW5ndGhfbW0qKiwgbGEgY3VhbCBkZWZpbmUgbGEgbG9uZ2l0dWQgZGUgbGEgYWxldGEgZGVsIGluZGl2aWR1byBtZWRpZGEgZW4gbWlsw61tZXRyb3MuIAoKUGFyYSB2aXN1YWxpemFyIGxvcyBudWV2b3Mgb3V0bGllcnMgYSBjb250aW51YWNpw7NuIGdyYWZpY2Ftb3MgKipmbGlwcGVyX2xlbmd0aF9tbSoqIHZzLiAgKipib2R5X21hc3NfZyoqIGFudGVzIHkgZGVzcHXDqXMgZGUgYWdyZWdhciBvdXRsaWVyczoKCmBgYHtyIGZpZy5hbGlnbj0nY2VudGVyJywgZmlnLmhlaWdodD0zLCBmaWcud2lkdGg9NSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgZmlnLmFsaWduPSdjZW50ZXInfQpwbG90X2RhdGEodHJhaW5fc2V0KQpgYGAKCmBgYHtyIGZpZy5hbGlnbj0nY2VudGVyJywgZmlnLmhlaWdodD0zLCBmaWcud2lkdGg9NSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgZmlnLmFsaWduPSdjZW50ZXInfQp0cmFpbl9zZXRfd2l0aF9vdXRsaWVycyA8LSB0cmFpbl9zZXQgJT4lCiAgbXV0YXRlKGZsaXBwZXJfbGVuZ3RoX21tID0gaWZlbHNlKAogICAgYm9keV9tYXNzX2cgPiA1NDAwICYgYm9keV9tYXNzX2cgPCA1NzAwLCAKICAgIGZsaXBwZXJfbGVuZ3RoX21tICsgKGZsaXBwZXJfbGVuZ3RoX21tICogcnVuaWYoMSwgMC4xLCAwLjIpKSwgCiAgICBmbGlwcGVyX2xlbmd0aF9tbQogICkpCgpwbG90X2RhdGEodHJhaW5fc2V0X3dpdGhfb3V0bGllcnMpCmBgYAoKIyMjIDIuIE1vZGVsbyBsaW5lYWwKCmBgYHtyfQpsaW5lYWxfbW9kZWxfMyA8LSBsbSgKICBib2R5X21hc3NfZyB+IGZsaXBwZXJfbGVuZ3RoX21tLAogIGRhdGEgPSB0cmFpbl9zZXRfd2l0aF9vdXRsaWVycwopCnN1bW1hcnkobGluZWFsX21vZGVsXzMpCmBgYAoKCkNvbXBhcmVtb3MgZWwgYWp1c3RlIGRlbCBtb2RlbG8gbGluZWFsIGFqdXN0YW5kbyBlbiB1biBkYXRhc2V0IGRlIHRyYWluIGNvbiB5IHNpbiBvdXRsaWVyczoKCmBgYHtyIGZpZy5hbGlnbj0nY2VudGVyJywgZmlnLmhlaWdodD0zLCBmaWcud2lkdGg9OCwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgZmlnLmFsaWduPSdjZW50ZXInfQpwbG90X2NvbXBhcmVfZml0KAogIGxpbmVhbF9tb2RlbF8xLCAKICBsaW5lYWxfbW9kZWxfMywgCiAgdHJhaW5fc2V0X3dpdGhfb3V0bGllcnMsCiAgbGFiZWxfMT0nUmVncmVzacOzbiBMaW5lYWwgU0lOIG91dGxpZXJzJywgCiAgbGFiZWxfMj0nUmVncmVzacOzbiBMaW5lYWwgQ09OIG91dGxpdGVycycKKQpgYGAKIApTZSBhcHJlY2lhIHF1ZSBlbCBtb2RlbG8gZW50cmVuYWRvIGVuICoqdHJhaW5fc2V0X291dGxpZXJzKiogZXN0YSBhcGFsYW5jYWRvIHBvciBsYXMgb2JzZXJ2YWNpb25lcyBhdMOtcGljYXMKCiMjIyAyLiBNb2RlbG8gbGluZWFsIFJvYnVzdG8KCkVudHJlbmFtb3MgdW5hIHJlZ3Jlc2nDs24gbGluZWFsIG3Dumx0aXBsZSByb2J1c3RhIHBhcmEgaW50ZW50YXIgZGUgZGlzbWludWlyIGVsIGVmZWN0byBkZSBsb3MgbnVldm9zIG91dGxpZXJzOgoKYGBge3J9CnJvYnVzdF9saW5lYWxfbW9kZWxfMyA8LSBybG0oCiAgYm9keV9tYXNzX2cgfiBmbGlwcGVyX2xlbmd0aF9tbSwKICBkYXRhID0gdHJhaW5fc2V0X3dpdGhfb3V0bGllcnMKKQpgYGAKCgpgYGB7ciBmaWcuYWxpZ249J2NlbnRlcicsIGZpZy5oZWlnaHQ9MywgZmlnLndpZHRoPTgsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGZpZy5hbGlnbj0nY2VudGVyJ30KcGxvdF9jb21wYXJlX2ZpdCgKICBsaW5lYWxfbW9kZWxfMSwgCiAgcm9idXN0X2xpbmVhbF9tb2RlbF8zLCAKICB0cmFpbl9zZXRfd2l0aF9vdXRsaWVycywKICBsYWJlbF8xPSdSZWdyZXNpw7NuIExpbmVhbCBTSU4gb3V0bGllcnMnLCAKICBsYWJlbF8yPSdSZWdyZXNpw7NuIExpbmVhbCBSb2J1c3RhIENPTiBvdXRsaXRlcnMnCikKYGBgCgpHcsOhZmljYW1lbnRlIG5vIHNlIGxsZWdhIGEgZGlzdGluZ3VpciBwZXJvIGVsIG1vZGVsbyByb2J1c3RvIHRlcm1pbmEgYWp1c3RhbmRvIG1lam9yIHF1ZSBlbCBtb2RlbG8gbGluZWFsIGNsw6FzaWNvLiBFc3RvIHNlIHB1ZWRlIG9ic2VydmFyIGN1YW5kbyBjb21wYXJhbW9zIGVsIFJNU0UvTUFFIHNvYnJlIHRyYWluIHkgdGVzdC4KCgpgYGB7cn0KbG1fdnNfbG1fbW9kZWxzX3ZhbGlkYXRpb24obGluZWFsX21vZGVsXzMsIHJvYnVzdF9saW5lYWxfbW9kZWxfMywgdHJhaW5fc2V0X3dpdGhfb3V0bGllcnMpCmBgYAoKCmBgYHtyfQpsbV92c19sbV9tb2RlbHNfdmFsaWRhdGlvbihsaW5lYWxfbW9kZWxfMywgcm9idXN0X2xpbmVhbF9tb2RlbF8zLCB0ZXN0X3NldCkKYGBgCgoKIyMjIDMuIE1vZGVsbyBiYXllc2lhbm8gY29uIExpa2VsaWhvb2Qgbm9ybWFsCgoKYGBge3IgZmlnLmFsaWduPSdjZW50ZXInLCBmaWcuaGVpZ2h0PTQsIGZpZy53aWR0aD04LCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBmaWcuYWxpZ249J2NlbnRlcid9CmJheWVzaW9uX21vZGVsXzMgPC0gc3RhbigKICBtb2RlbF9jb2RlID0gICIKICAgIGRhdGEgewogICAgICBpbnQ8bG93ZXI9MT4gICAgICAgICAgICAgICBvYnNfY291bnQ7CiAgICAgIHZlY3Rvcjxsb3dlcj0xPltvYnNfY291bnRdIHg7CiAgICAgIHZlY3RvcltvYnNfY291bnRdICAgICAgICAgIHk7CiAgICB9CiAgICBwYXJhbWV0ZXJzIHsKICAgICAgcmVhbCAgICAgICAgICBiZXRhMDsKICAgICAgcmVhbCAgICAgICAgICBiZXRhMTsKICAgICAgcmVhbDxsb3dlcj0wPiBzaWdtYTsKICAgIH0KICAgIG1vZGVsIHsKICAgICAgLy8gRGlzdHJpYnVjaW9uZXMgYSBwcmlvcmkgKEZpamFkbyBwb3IgZWwgaW52ZXN0aWdhZG9yKQogICAgICBiZXRhMCB+IG5vcm1hbCgwLCAxMDAwKTsgIC8vIEludGVyY2VwdAogICAgICBiZXRhMSB+IG5vcm1hbCgwLCAxMDApOyAgIC8vIGZsaXBwZXJfbGVuZ3RoX21tCiAgICAgIHNpZ21hIH4gZXhwb25lbnRpYWwoMC4xKTsgLy8gVmFyaWFuemEKCiAgICAgIC8vIExpa2VsaWhvb2QKICAgICAgeSB+IG5vcm1hbChiZXRhMCArIGJldGExICogeCwgc2lnbWEpOwogICAgfQogICIsCiAgZGF0YSA9IGxpc3QoCiAgICAgIG9ic19jb3VudCA9IG5yb3codHJhaW5fc2V0X3dpdGhfb3V0bGllcnMpLAogICAgICB4ID0gY29sdmFsdWVzKHRyYWluX3NldF93aXRoX291dGxpZXJzLCAnZmxpcHBlcl9sZW5ndGhfbW0nKSwKICAgICAgeSA9IGNvbHZhbHVlcyh0cmFpbl9zZXRfd2l0aF9vdXRsaWVycywgJ2JvZHlfbWFzc19nJykKICApLAogIGNoYWlucyA9IDMsCiAgaXRlciAgID0gMTAwMCwKICB3YXJtdXAgPSAzMDAsCiAgdGhpbiAgID0gMQopCgpwYXJhbXNfMyA8LSBjKCdiZXRhMCcsICdiZXRhMScsICdzaWdtYScpCnRyYWNlcGxvdChiYXllc2lvbl9tb2RlbF8zLCBwYXJzID0gcGFyYW1zXzMsIGluY193YXJtdXAgPSBUUlVFKQpgYGAKCgojIyMgNC4gQ29lZmljaWVudGVzCgpgYGB7cn0KbG1fdnNfYnJfY29lZmljaWVudHMocm9idXN0X2xpbmVhbF9tb2RlbF8zLCBiYXllc2lvbl9tb2RlbF8zLCBwYXJhbXNfMykKYGBgCgojIyMgNS4gVmFsaWRhY2nDs24KCgpgYGB7cn0KdmFyc18zIDwtIGMoJ2ZsaXBwZXJfbGVuZ3RoX21tJykgCgpsbV92c19icl9tb2RlbHNfdmFsaWRhdGlvbihyb2J1c3RfbGluZWFsX21vZGVsXzMsIGJheWVzaW9uX21vZGVsXzMsIHBhcmFtc18zLCB2YXJzXzMsIHRlc3Rfc2V0KQpgYGAKCmBgYHtyIGZpZy5hbGlnbj0nY2VudGVyJywgZmlnLmhlaWdodD0zLCBmaWcud2lkdGg9OCwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgZmlnLmFsaWduPSdjZW50ZXInfQpiYXllc2lvbl9wcmVkaWN0b3JfMyA8LSBCYXllc2lhblJlZ3Jlc3Npb25QcmVkaWN0b3IuZnJvbShiYXllc2lvbl9tb2RlbF8zLCBwYXJhbXNfMywgdmFyc18zKQoKcGxvdF9jb21wYXJlX2ZpdCgKICByb2J1c3RfbGluZWFsX21vZGVsXzMsIAogIGJheWVzaW9uX3ByZWRpY3Rvcl8zLCAKICB0cmFpbl9zZXQsCiAgbGFiZWxfMT0nUmVncmVzaW9uIExpbmVhbCBSb2J1c3RhIENPTiBvdXRsaWVycycsIAogIGxhYmVsXzI9J1JlZ3Jlc2lvbiBCYXllc2lhbmEgQ09OIG91dGxpZXJzJwopCmBgYAoKCiMjIyA2LiBNb2RlbG8gYmF5ZXNpYW5vIGNvbiBMaWtlbGlob29kIHQtc3R1ZGVudAoKCmBgYHtyIGZpZy5hbGlnbj0nY2VudGVyJywgZmlnLmhlaWdodD00LCBmaWcud2lkdGg9OCwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgZmlnLmFsaWduPSdjZW50ZXInfQpiYXllc2lvbl9tb2RlbF8zLjEgPC0gc3RhbigKICBtb2RlbF9jb2RlID0gICIKICAgIGRhdGEgewogICAgICBpbnQ8bG93ZXI9MT4gICAgICAgICAgICAgICBvYnNfY291bnQ7CiAgICAgIHZlY3Rvcjxsb3dlcj0xPltvYnNfY291bnRdIHg7CiAgICAgIHZlY3RvcltvYnNfY291bnRdICAgICAgICAgIHk7CiAgICB9CiAgICBwYXJhbWV0ZXJzIHsKICAgICAgcmVhbCAgICAgICAgICBiZXRhMDsKICAgICAgcmVhbCAgICAgICAgICBiZXRhMTsKICAgICAgcmVhbDxsb3dlcj0wPiBzaWdtYTsKICAgIH0KICAgIG1vZGVsIHsKICAgICAgLy8gRGlzdHJpYnVjaW9uZXMgYSBwcmlvcmkgKEZpamFkbyBwb3IgZWwgaW52ZXN0aWdhZG9yKQogICAgICBiZXRhMCB+IG5vcm1hbCgtNTcwMCwgNTApOyAgLy8gSW50ZXJjZXB0IChNdXkgaW5mb3JtYXRpdmEhISEpCiAgICAgIGJldGExIH4gbm9ybWFsKDQ5LCAyMCk7ICAgICAgLy8gZmxpcHBlcl9sZW5ndGhfbW0gKE11eSBpbmZvcm1hdGl2YSEhISkKICAgICAgc2lnbWEgfiBleHBvbmVudGlhbCgwLjEpOyAvLyBWYXJpYW56YQoKICAgICAgLy8gTGlrZWxpaG9vZAogICAgICB5IH4gc3R1ZGVudF90KDIsIGJldGEwICsgYmV0YTEgKiB4LCBzaWdtYSk7CiAgICB9CiAgIiwKICBkYXRhID0gbGlzdCgKICAgICAgb2JzX2NvdW50ID0gbnJvdyh0cmFpbl9zZXRfd2l0aF9vdXRsaWVycyksCiAgICAgIHggPSBjb2x2YWx1ZXModHJhaW5fc2V0X3dpdGhfb3V0bGllcnMsICdmbGlwcGVyX2xlbmd0aF9tbScpLAogICAgICB5ID0gY29sdmFsdWVzKHRyYWluX3NldF93aXRoX291dGxpZXJzLCAnYm9keV9tYXNzX2cnKQogICksCiAgY2hhaW5zID0gMywKICBpdGVyICAgPSAxMDAwLAogIHdhcm11cCA9IDMwMCwKICB0aGluICAgPSAxCikKCnBhcmFtc18zIDwtIGMoJ2JldGEwJywgJ2JldGExJywgJ3NpZ21hJykKdHJhY2VwbG90KGJheWVzaW9uX21vZGVsXzMuMSwgcGFycyA9IHBhcmFtc18zLCBpbmNfd2FybXVwID0gVFJVRSkKYGBgCgojIyMgNy4gQ29lZmljaWVudGVzCgpgYGB7cn0KbG1fdnNfYnJfY29lZmljaWVudHMobGluZWFsX21vZGVsXzEsIGJheWVzaW9uX21vZGVsXzMuMSwgcGFyYW1zXzMpCmBgYAoKIyMjIDguIFZhbGlkYWNpw7NuCgoKYGBge3J9CnZhcnNfMyA8LSBjKCdmbGlwcGVyX2xlbmd0aF9tbScpIAoKbG1fdnNfYnJfbW9kZWxzX3ZhbGlkYXRpb24obGluZWFsX21vZGVsXzEsIGJheWVzaW9uX21vZGVsXzMuMSwgcGFyYW1zXzMsIHZhcnNfMywgdGVzdF9zZXQpCmBgYAoKYGBge3IgZmlnLmFsaWduPSdjZW50ZXInLCBmaWcuaGVpZ2h0PTMsIGZpZy53aWR0aD04LCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBmaWcuYWxpZ249J2NlbnRlcid9CmJheWVzaW9uX3ByZWRpY3Rvcl8zLjEgPC0gQmF5ZXNpYW5SZWdyZXNzaW9uUHJlZGljdG9yLmZyb20oYmF5ZXNpb25fbW9kZWxfMy4xLCBwYXJhbXNfMywgdmFyc18zKQoKcGxvdF9jb21wYXJlX2ZpdCgKICBsaW5lYWxfbW9kZWxfMSwgCiAgYmF5ZXNpb25fcHJlZGljdG9yXzMuMSwgCiAgdHJhaW5fc2V0X3dpdGhfb3V0bGllcnMsCiAgbGFiZWxfMT0nUmVncmVzaW9uIExpbmVhbCBTSU4gb3V0bGllcnMnLCAKICBsYWJlbF8yPSdSZWdyZXNpb24gQmF5ZXNpYW5hIENPTiBvdXRsaWVycycKKQpgYGAKCiMjIEV4cGVyaW1lbnRvIDQKCgoqIElkZW0gZXhwZXJpbWVudG8gMSBwZXJvIHJlZHVjaWVuZG8gbGEgY2FudGlkYWQgZGUgb2JzZXJ2YWNpb25lcyBhIHBvY29zIHZhbG9yZXMgKGVqOjMwKS4KKiBSZWdyZXNpw7NuIG3Dumx0aXBsZSBmcmVjdWVudGlzdGEuCiogUmVncmVzacOzbiBiYXllc2lhbmEgY29uIHByaW9ycyBub3JtYWxlcyB5IGV4cG9uZW5jaWFsLgoKCiMjIyAxLiBTcGxpdCB0cmFpbiAtIHRlc3QKCkVuIGVzdGUgYXNvIGVudHJlbmFtb3Mgc29sbyBjb24gZWwgMTAlIGRlIGxvIGRhdG9zLgoKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KdHJhaW5fdGVzdCA8LSB0cmFpbl90ZXN0X3NwbGl0KGRhdGFzZXQsIHRyYWluX3NpemUgPSAwLjA1LCBzaHVmZmxlID0gVFJVRSkKdHJhaW5fc2V0XzQgPC0gdHJhaW5fdGVzdFtbMV1dCnRlc3Rfc2V0XzQgIDwtIHRyYWluX3Rlc3RbWzJdXQpgYGAKCmBgYHtyIGZpZy5hbGlnbj0nY2VudGVyJywgZmlnLmhlaWdodD0zLCBmaWcud2lkdGg9NSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgZmlnLmFsaWduPSdjZW50ZXInfQpwbG90X2RhdGEodHJhaW5fc2V0XzQpCmBgYAoKIyMjIDIuIE1vZGVsbyBsaW5lYWwKCmBgYHtyfQpsaW5lYWxfbW9kZWxfNCA8LSBsbSgKICBib2R5X21hc3NfZyB+IGZsaXBwZXJfbGVuZ3RoX21tLAogIGRhdGEgPSB0cmFpbl9zZXRfNAopCmBgYAoKIyMjIDMuIE1vZGVsbyBiYXllc2lhbm8KCmBgYHtyIGZpZy5hbGlnbj0nY2VudGVyJywgZmlnLmhlaWdodD00LCBmaWcud2lkdGg9OCwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgZmlnLmFsaWduPSdjZW50ZXInfQpiYXllc2lvbl9tb2RlbF80IDwtIHN0YW4oCiAgbW9kZWxfY29kZSA9ICAiCiAgICBkYXRhIHsKICAgICAgaW50PGxvd2VyPTE+ICAgICAgICAgICAgICAgb2JzX2NvdW50OwogICAgICB2ZWN0b3I8bG93ZXI9MT5bb2JzX2NvdW50XSB4OwogICAgICB2ZWN0b3Jbb2JzX2NvdW50XSAgICAgICAgICB5OwogICAgfQogICAgcGFyYW1ldGVycyB7CiAgICAgIHJlYWwgICAgICAgICAgYmV0YTA7CiAgICAgIHJlYWwgICAgICAgICAgYmV0YTE7CiAgICAgIHJlYWw8bG93ZXI9MD4gc2lnbWE7CiAgICB9CiAgICBtb2RlbCB7CiAgICAgIC8vIERpc3RyaWJ1Y2lvbmVzIGEgcHJpb3JpCiAgICAgIGJldGEwIH4gbm9ybWFsKDAsIDgwMDApOyAvLyBJbnRlcmNlcHQKICAgICAgYmV0YTEgfiBub3JtYWwoMCwgMTAwKTsKICAgICAgc2lnbWEgfiBleHBvbmVudGlhbCgwLjEpOwogICAgCiAgICAgIC8vIExpa2VsaWhvb2QKICAgICAgeSB+IG5vcm1hbChiZXRhMCArIGJldGExICogeCwgc2lnbWEpOwogICAgfQogICIsCiAgZGF0YSA9IGxpc3QoCiAgICAgIG9ic19jb3VudCA9IG5yb3codHJhaW5fc2V0XzQpLAogICAgICB4ID0gY29sdmFsdWVzKHRyYWluX3NldF80LCAnZmxpcHBlcl9sZW5ndGhfbW0nKSwKICAgICAgeSAgPSBjb2x2YWx1ZXModHJhaW5fc2V0XzQsICdib2R5X21hc3NfZycpCiAgKSwKICBjaGFpbnMgPSAzLAogIGl0ZXIgICA9IDMwMCwKICB3YXJtdXAgPSAxODAsCiAgdGhpbiAgID0gMQopCgpwYXJhbXNfNCA8LSBjKCdiZXRhMCcsICdiZXRhMScsICdzaWdtYScpCnRyYWNlcGxvdChiYXllc2lvbl9tb2RlbF80LCBwYXJzID0gcGFyYW1zXzQsIGluY193YXJtdXAgPSBUUlVFKQpgYGAKCiMjIyA0LiBDb2VmaWNpZW50ZXMKCkNvZWZpY2llbnRlcyBkZSBsYSByZWdyZXNpw7NuIG3Dumx0aXBsZToKCgpgYGB7cn0KbGluZWFsX21vZGVsXzQkY29lZmZpY2llbnRzCmBgYAoKQ29lZmljaWVudGVzIGRlc2N1YmllcnRvcyBwb3IgbGEgcmVncmVzacOzbiBtw7psdGlwbGUgYmF5ZXNpYW5hOgoKYGBge3J9CmZvcihwYXJhbSBpbiBwYXJhbXNfNCkgcHJpbnQoZ2V0X3Bvc3Rlcmlvcl9tZWFuKGJheWVzaW9uX21vZGVsXzQsIHBhcj1wYXJhbSlbNF0pCmBgYAoKCiMjIyA1LiBWYWxpZGFjacOzbgoKCmBgYHtyfQp2YXJzXzQgPC0gYygnZmxpcHBlcl9sZW5ndGhfbW0nKSAKCmxtX3ZzX2JyX21vZGVsc192YWxpZGF0aW9uKGxpbmVhbF9tb2RlbF80LCBiYXllc2lvbl9tb2RlbF80LCBwYXJhbXNfNCwgdmFyc180LCB0ZXN0X3NldCkKYGBgCgpgYGB7ciBmaWcuYWxpZ249J2NlbnRlcicsIGZpZy5oZWlnaHQ9MywgZmlnLndpZHRoPTUsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGZpZy5hbGlnbj0nY2VudGVyJ30KYmF5ZXNpb25fcHJlZGljdG9yXzQgPC0gQmF5ZXNpYW5SZWdyZXNzaW9uUHJlZGljdG9yLmZyb20oYmF5ZXNpb25fbW9kZWxfNCwgcGFyYW1zXzQsIHZhcnNfNCkKCnBsb3RfY29tcGFyZV9maXQoCiAgbGluZWFsX21vZGVsXzQsCiAgYmF5ZXNpb25fcHJlZGljdG9yXzQsIAogIHRyYWluX3NldCwKICBsYWJlbF8xPSdSZWdyZXNpb24gTGluZWFsJywgCiAgbGFiZWxfMj0nUmVncmVzaW9uIEJheWVzaWFuYScKKQpgYGAKCgojIyBFeHBlcmltZW50byA1CgoqIElndWFsIGFsIGV4cGVyaW1lbnRvIDEgcGVybyBwcm9wb25pZW5kbyBkb3MgbnVldmFzIHJlZ3Jlc2lvbmVzIGJheWVzaWFuYXMgY29uIHByaW9ycyBwYXJhIGxvcyBwYXLDoW1ldHJvcyBxdWUgc2VhbjoKICAqIFVuYSBwb2NhIGluZm9ybWF0aXZhICh1bmlmb3JtZSkuCiAgKiBVbmEgbXV5IGluZm9ybWF0aXZhIChzZXNnYWRhIG8gY29uIG11eSBwb2NhIHZhcmlhbnphKS4KKiBDb21wYXJhciBjb24gcmVzdWx0YWRvcyBkZSBsYSBiYXllc2lhbmEgZGVsIGV4cGVyaW1lbnRvIEEKCiMjIyAxLiBNb2RlbG8gYmF5ZXNpYW5vIGNvbiBwYXJhbWV0cm8gY29uIGRpc3RyaWJ1Y2lvbiBwb2NvIGluZm9ybWF0aXZhCgojIyMjIDEuIE1vZGVsbwoKRGVmaW5pbW9zIHVuYSBbZGlzdHJpYnVjacOzbiB1bmlmb3JtZV0oaHR0cHM6Ly9tYy1zdGFuLm9yZy9kb2NzLzJfMjEvZnVuY3Rpb25zLXJlZmVyZW5jZS91bmlmb3JtLWRpc3RyaWJ1dGlvbi5odG1sKSBwYXJhIGVsIGJldGEgYXNvY2lhZG8gYSBsYSB2YXJpYWJsZSAqKmZsaXBwZXJfbGVuZ3RoX21tKiouCgpgYGB7ciBmaWcuYWxpZ249J2NlbnRlcicsIGZpZy5oZWlnaHQ9NCwgZmlnLndpZHRoPTgsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGZpZy5hbGlnbj0nY2VudGVyJywgZWNobz1GQUxTRX0KYmF5ZXNpb25fbW9kZWxfNSA8LSBzdGFuKAogIG1vZGVsX2NvZGUgPSAgIgogICAgZGF0YSB7CiAgICAgIGludDxsb3dlcj0xPiAgICAgICAgICAgICAgIG9ic19jb3VudDsKICAgICAgdmVjdG9yPGxvd2VyPTE+W29ic19jb3VudF0geDsKICAgICAgdmVjdG9yW29ic19jb3VudF0gICAgICAgICAgeTsKICAgIH0KICAgIHBhcmFtZXRlcnMgewogICAgICByZWFsICAgICAgICAgIGJldGEwOwogICAgICByZWFsICAgICAgICAgIGJldGExOwogICAgICByZWFsPGxvd2VyPTA+IHNpZ21hOwogICAgfQogICAgbW9kZWwgewogICAgICAvLyBEaXN0cmlidWNpb25lcyBhIHByaW9yaQogICAgICBiZXRhMCB+IG5vcm1hbCgwLCA4MDAwKTsgLy8gSW50ZXJjZXB0CiAgICAgIGJldGExIH4gbm9ybWFsKDAsIDEwMCk7CiAgICAgIHNpZ21hIH4gZXhwb25lbnRpYWwoMC41KTsKICAKICAgICAgLy8gTGlrZWxpaG9vZAogICAgICB5IH4gbm9ybWFsKGJldGEwICsgYmV0YTEgKiB4LCBzaWdtYSk7CiAgICB9CiAgIiwKICBkYXRhID0gbGlzdCgKICAgICAgb2JzX2NvdW50ID0gbnJvdyh0cmFpbl9zZXQpLAogICAgICB4ID0gY29sdmFsdWVzKHRyYWluX3NldCwgJ2ZsaXBwZXJfbGVuZ3RoX21tJyksCiAgICAgIHkgID0gY29sdmFsdWVzKHRyYWluX3NldCwgJ2JvZHlfbWFzc19nJykKICApLAogIGNoYWlucyA9IDMsCiAgaXRlciAgID0gMTAwMCwKICB3YXJtdXAgPSAxODAsCiAgdGhpbiAgID0gMQopCgpwYXJhbXNfNSA8LSBjKCdiZXRhMCcsICdiZXRhMScsICdzaWdtYScpCnRyYWNlcGxvdChiYXllc2lvbl9tb2RlbF81LCBwYXJzID0gcGFyYW1zXzUsIGluY193YXJtdXAgPSBUUlVFKQpgYGAKCgojIyMjIDIuIENvZWZpY2llbnRlcwoKCmBgYHtyfQpicl92c19icl9jb2VmaWNpZW50cyhiYXllc2lvbl9tb2RlbF8xLCBiYXllc2lvbl9tb2RlbF81LCBwYXJhbXNfNSkKYGBgCgoKIyMjIyAzLiBWYWxpZGFjacOzbgoKYGBge3J9CmxtX3ZzX2JyX21vZGVsc192YWxpZGF0aW9uKGxpbmVhbF9tb2RlbF8xLCBiYXllc2lvbl9tb2RlbF8xLCBwYXJhbXNfMSwgdmFyc18xLCB0ZXN0X3NldCkKYGBgCiMjIyMgNC4gVmFsaWRhY2lvbgoKYGBge3J9CnZhcnNfNSA8LSBjKCdmbGlwcGVyX2xlbmd0aF9tbScpIAoKbG1fdnNfYnJfbW9kZWxzX3ZhbGlkYXRpb24obGluZWFsX21vZGVsXzEsIGJheWVzaW9uX21vZGVsXzUsIHBhcmFtc181LCB2YXJzXzUsIHRlc3Rfc2V0KQpgYGAKCmBgYHtyIGZpZy5hbGlnbj0nY2VudGVyJywgZmlnLmhlaWdodD0zLCBmaWcud2lkdGg9MTAsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGZpZy5hbGlnbj0nY2VudGVyJ30KYmF5ZXNpb25fcHJlZGljdG9yXzUgPC0gQmF5ZXNpYW5SZWdyZXNzaW9uUHJlZGljdG9yLmZyb20oYmF5ZXNpb25fbW9kZWxfNSwgcGFyYW1zXzUsIHZhcnNfNSkKCnBsb3RfY29tcGFyZV9maXQoCiAgYmF5ZXNpb25fcHJlZGljdG9yXzEsCiAgYmF5ZXNpb25fcHJlZGljdG9yXzUsCiAgdHJhaW5fc2V0LAogIGxhYmVsXzE9J1JlZ3Jlc2lvbiBCYXllc2lhbmEgY29uIGRpc3QgaW5mb3JtYXRpdmEnLCAKICBsYWJlbF8yPSdSZWdyZXNpb24gQmF5ZXNpYW5hIGNvbiBkaXN0IG1lbm9zIGluZm9ybWF0aXZhJwopCmBgYAoKIyMjIDIuIE1vZGVsbyBiYXllc2lhbm8gY29uIHBhcmFtZXRybyBjb24gZGlzdHJpYnVjaW9uIG11eSBpbmZvcm1hdGl2YSBzZXNnYWRhIG8gY29uIHBvY2EgdmFyaWFuemEKCkNPTVBMRVRBUgoKCgojIyBSZWZlcmVuY2lhcwoKKiBbTWFraW5nIFByZWRpY3Rpb25zIGZyb20gU3RhbiBtb2RlbHMgaW4gUl0oaHR0cHM6Ly9tZWRpdW0uY29tL0BhbGV4LnBhdmxha2lzL21ha2luZy1wcmVkaWN0aW9ucy1mcm9tLXN0YW4tbW9kZWxzLWluLXItM2UzNDlkZmFjMWVkKQoqIFtIb3cgdG8gcmVwcmVzZW50IGEgY2F0ZWdvcmljYWwgcHJlZGljdG9yIHJzdGFuP10oaHR0cHM6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvMjkxODM1NzcvaG93LXRvLXJlcHJlc2VudC1hLWNhdGVnb3JpY2FsLXByZWRpY3Rvci1yc3RhbikKCg==